MySQLのテーブルの修復

この間久しぶりにCounterize IIの画面を開いた。
全然アクセス数とか気にしなくなっていたので気づくのが遅れたのだけども、いつからかわからないけどもずっとアクセスが0という扱いになっていた。
さすがにアクセス0ということはないので、おそらくデータベースに異常が発生しているんじゃないかと思った。
プラグインの異常ということも考えたけども、ぐぐってみても別にそういう話はヒットしなかったからだ。

で、テーブルの構造とかに間違いがないかを調べていたら、なにやら変なエラーが発生した。
ERROR 145 (HY000)
どういうエラーなのか調べてみたら、どうやらテーブルが破損しているということらしい。
MyISAMテーブルのチェックはmyisamchkでできる。
データベースのデータ格納ディレクトリで

myisamchk -e *.MYI

とかすればチェックできる。
でしらべてみると

Checking MyISAM file: wp_Counterize.MYI
Data records:  267703   Deleted blocks:       0
myisamchk: warning: 9 clients are using or haven't closed the table properly
- check file-size
myisamchk: warning: Size of datafile is: 12830392        Should be: 12830056
- check record delete-chain
- check key delete-chain
- check index reference
- check data record references index: 1
myisamchk: error: Found 267710 keys of 267703
- check records and index references
myisamchk: error: Record-count is not ok; is 267710       Should be: 267703
myisamchk: warning: Found     267710 parts                Should be: 267703 parts
MyISAM-table 'wp_Counterize.MYI' is corrupted
Fix it using switch "-r" or "-o"

とか出てきた。
そこで、

myisamchk -r wp_Counterize

としたところ、治った模様。

ところで、MySQLさんはテーブルに異常が発生していたら勝手に通知してくれたり修復してくれたりしないのだろうか。
まったくもって気づかなかった。
ログにこっそりはき出されていたりするのかな。
メール通知オプションとかほしいな。
あるのかもしれないけど調べる気もとりあえず今はないでござる。

LVMのスナップショットの動作が怪しい

うちのサーバ機はxenを使って仮想化して運用している。
そして毎日定期バックアップをLVMのスナップショット機能を利用して行っているのだけども、どうも最近挙動がおかしいことに気づいた。
作成したスナップショットが高確率でファイルシステムにエラーを含んでいる。

# xm pause debian
# lvcreate -s -n snapdebian -L 200G /dev/ms09/debian
  Logical volume "snapdebian" created
# xm unpause debian

としてスナップショットを作成する。
ここまではいい。
が、ここでfsckを走らせるとエラーが出る。

# e2fsck -yfv /dev/ms09/snapdebian
e2fsck 1.41.12 (17-May-2010)
/dev/ms09/snapdebian: recovering journal
Clearing orphaned inode 15466504 (uid=109, gid=109, mode=0100600, size=0)
Clearing orphaned inode 15466503 (uid=109, gid=109, mode=0100600, size=0)
Clearing orphaned inode 15466502 (uid=109, gid=109, mode=0100600, size=0)
Clearing orphaned inode 15466501 (uid=109, gid=109, mode=0100600, size=20)
Clearing orphaned inode 15466500 (uid=109, gid=109, mode=0100600, size=0)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information

/dev/ms09/snapdebian: ***** FILE SYSTEM WAS MODIFIED *****

  715619 inodes used (2.13%)
     738 non-contiguous files (0.1%)
     182 non-contiguous directories (0.0%)
         # of inodes with ind/dind/tind blocks: 0/0/0
         Extent depth histogram: 706955/133
23572155 blocks used (17.56%)
       0 bad blocks
       6 large files

  677160 regular files
   29784 directories
     126 character device files
      40 block device files
       2 fifos
      16 links
    8469 symbolic links (8324 fast symbolic links)
      29 sockets
--------
  715626 files

マウントしてrsyncでバックアップをとるとumountでえらい時間がかかる。
カーネルが文句いってる。

[  647.099517] EXT4-fs (dm-18): ext4_orphan_cleanup: deleting unreferenced inode 15466504
[  647.099539] EXT4-fs (dm-18): ext4_orphan_cleanup: deleting unreferenced inode 15466503
[  647.099548] EXT4-fs (dm-18): ext4_orphan_cleanup: deleting unreferenced inode 15466502
[  647.099556] EXT4-fs (dm-18): ext4_orphan_cleanup: deleting unreferenced inode 15466501
[  647.099591] EXT4-fs (dm-18): ext4_orphan_cleanup: deleting unreferenced inode 15466500
[  647.099599] EXT4-fs (dm-18): 5 orphan inodes deleted
[  647.099710] EXT4-fs (dm-18): recovery complete
[  647.433114] EXT4-fs (dm-18): mounted filesystem with ordered data mode
[ 1080.113046] INFO: task umount:4061 blocked for more than 120 seconds.
[ 1080.113114] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 1080.113201] umount        D 0000000000000000     0  4061   2294 0x00000000
[ 1080.113331]  ffffffff8147b1f0 0000000000000282 0000000000000000 ffff8801e6971de8
[ 1080.113544]  0000000000000000 0000000000000000 000000000000f9e0 ffff8801e6971fd8
[ 1080.117004]  0000000000015780 0000000000015780 ffff8801c17654c0 ffff8801c17657b8
[ 1080.117004] Call Trace:
[ 1080.117004]  [<ffffffff8100e629>] ? xen_force_evtchn_callback+0x9/0xa
[ 1080.117004]  [<ffffffff8100ece2>] ? check_events+0x12/0x20
[ 1080.117004]  [<ffffffff8110926b>] ? bdi_sched_wait+0x0/0xe
[ 1080.117004]  [<ffffffff81109274>] ? bdi_sched_wait+0x9/0xe
[ 1080.117004]  [<ffffffff8130d19a>] ? _spin_unlock_irqrestore+0xd/0xe
[ 1080.117004]  [<ffffffff8130c3e7>] ? __wait_on_bit+0x41/0x70
[ 1080.117004]  [<ffffffff8100f0ac>] ? xen_smp_send_reschedule+0x0/0x7
[ 1080.117004]  [<ffffffff8110926b>] ? bdi_sched_wait+0x0/0xe
[ 1080.117004]  [<ffffffff8130c481>] ? out_of_line_wait_on_bit+0x6b/0x77
[ 1080.117004]  [<ffffffff81065f24>] ? wake_bit_function+0x0/0x23
[ 1080.117004]  [<ffffffff811092ec>] ? sync_inodes_sb+0x73/0x12a
[ 1080.117004]  [<ffffffff8110cea1>] ? __sync_filesystem+0x4b/0x70
[ 1080.117004]  [<ffffffff810f1aa2>] ? generic_shutdown_super+0x21/0xfa
[ 1080.117004]  [<ffffffff8100eccf>] ? xen_restore_fl_direct_end+0x0/0x1
[ 1080.117004]  [<ffffffff810f1b9d>] ? kill_block_super+0x22/0x3a
[ 1080.117004]  [<ffffffff810f226d>] ? deactivate_super+0x60/0x77
[ 1080.117004]  [<ffffffff81104bc0>] ? sys_umount+0x2dc/0x30b
[ 1080.117004]  [<ffffffff81011b42>] ? system_call_fastpath+0x16/0x1b

場合によってはこのままumountできずにプロセスが残り続けて死ねる。
とりあえずディスクI/Oがロックされた状態になるんだろう。

この問題は稼働中のext4ファイルシステムのスナップショットを作成した際に起きるようだ。
おそらくジャーナルに書き出したデータが実データに反映されていないような状況でスナップショットを作成した場合に起きるんじゃないかと予測している。
のでext3でも同じ現象が起きるだろう。たぶん。
まあ、別にそれでも変更差分をきちんと吸収してくれているならかまわないんだけども、使い終わったスナップショットをアンマウントするのになんで何分もかかるのかがわからない。

その上、使用済みのスナップショットボリュームを削除しようとしても失敗することがある。

# lvremove -f /dev/ms09/snapdebian
  Unable to deactivate open ms09-debian-real (254:5)
  Failed to resume debian.

これに関してはバグレポートが見つかった
とりあえず4ヶ月経過しても治っていないらしい。

んーむ。
こうなるとバックアップ手法を見直す必要性が出てくる。
Dom0とDomUとで疑似遠隔rsyncでバックアップとなるのだろうか。
だけどそれだとrootでのリモートログインが必要となるから駄目だな。
ゲストはゲストでバックアップパーティションをディスクとしてアタッチして、各自でバックアップしてもらうような形ならいけるか。

あー、設定するのがめんどくさい。

LVMでのfstab記述メモ

最近はfstabに記述するデバイスをUUIDで記述することが主流になっている。ような気がする。
UUIDで記述すればデバイスの順序が入れ替わったりしても問題ないからだ。
が、LVMではスナップショットを利用する際やミラーリングを行っていたりしていると、UUIDが重複するファイルシステムが複数現れたりする。
ので、従来通りデバイスのパスを記述する方が無難だと思う。
それだけ。

ブートパーティションをミラーリングする

mdadmを用いてブートパーティションをRAID1で運用するように切り替える。
既存運用の/bootをsda1, 新規追加パーティションをsdb1とする。
とりあえずやる前に/bootのバックアップはとっとこね。

ということでまずsdb1をレイドアレイとして構築する。
まず、fdiskでsdb1のパーティションシステムIDをLinux raid auto(0xfd)に設定する。
やり方がわからなかったらぐぐろう。
そしraidアレイを構築する。
(結論から言うとこれにさらに –metadata=0.9 のオプションが必要だった)

# mdadm --create /dev/md1 --level=1 --raid-devices=2 missing /dev/sdb1

構築できたら情報をmdadm.confに記録する。

# mdadm --detail --scan >> /etc/mdadm/mdadm.conf

/etc/fstabのを環境に合わせて修正。

/dev/sda1 /boot ext3 defaults 0 2
から
/dev/md1 /boot ext3 defaults 0 2
みたいな

initramfsの更新。

# update-initramfs -k all -ut

必要があればgrub関係の修正をしてupdate-grub。
(rootデバイスがmdになる場合など)

sdb1だけで構築されている方肺のmd1にファイルシステムを作成して/bootの内容を移す。

# mke2fs -t ext3 /dev/md1
# mount -t ext3 /dev/md1 /mnt/temp/
# cp -pr /boot/* /mnt/temp/
# umount /mnt/temp

最後にsda1をRAIDに追加する。

# mdadm --add /dev/md1 /dev/sda1

fdiskでファイルシステムIDもfdに変えておく。
でいけるかと思ったんだけども、error 2が発生して起動しない。
grubをMBRに再セットアップしようとしてもfilesystem type unknownと言われたりしてうまくいかない。
果てさて、どうしてこうなった。

ということで調べていたらこんな記事を見つけた。
同じ現象だ。
要約すると、mdadmで構築するRAIDのメタデータのバージョンがデフォルトだと1.2だけど、grubは1.2に対応してないから0.9で作ろうね、っていうことらしい。
ということで、RAIDを構築する時のオプションに –metadata=0.9 を付け加えてやり直した。
いけた。
罠すぎた。

debian sidでupgradeしたら死んだ

とりあえずどういうことかというとログを張った方が早い。

# aptitude upgrade
(中略)
libc6-i386 2.13-16 を (.../libc6-i386_2.13-19_amd64.deb で) 置換するための準備をしています ...
libc6-i386 を展開し、置換しています...
libc-dev-bin 2.13-16 を (.../libc-dev-bin_2.13-19_amd64.deb で) 置換するための準備をしています ...
libc-dev-bin を展開し、置換しています...
libc6-dev 2.13-16 を (.../libc6-dev_2.13-19_amd64.deb で) 置換するための準備をしています ...
libc6-dev を展開し、置換しています...
libc-bin 2.13-16 を (.../libc-bin_2.13-19_amd64.deb で) 置換するための準備をしています ...
libc-bin を展開し、置換しています...
man-db のトリガを処理しています ...
libc-bin (2.13-19) を設定しています ...
(データベースを読み込んでいます ... 現在 52504 個のファイルとディレクトリがインストールされています。)
libc6 2.13-16 を (.../libc6_2.13-19_amd64.deb で) 置換するための準備をしています ...
/var/lib/dpkg/tmp.ci/preinst: line 141: /bin/mv: No such file or directory
dpkg: /var/cache/apt/archives/libc6_2.13-19_amd64.deb の処理中にエラーが発生しました (--unpack):
 サブプロセス 新しい pre-installation スクリプト はエラー終了ステータス 1 を返しました
dpkg (サブプロセス): 新しい post-removal スクリプト を実行できません (/var/lib/dpkg/tmp.ci/postrm): そのようなファイルやディレクトリはありません
dpkg: クリーンアップ中にエラーが発生しました:
 サブプロセス 新しい post-removal スクリプト はエラー終了ステータス 2 を返しました
dpkg (サブプロセス): rm command for cleanup を実行できません (rm): そのようなファイルやディレクトリはありません
dpkg: クリーンアップ中にエラーが発生しました:
 サブプロセス rm cleanup はエラー終了ステータス 2 を返しました
以下のパッケージの処理中にエラーが発生しました:
 /var/cache/apt/archives/libc6_2.13-19_amd64.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)
パッケージをインストールできませんでした。復旧を試みています:

現在の状態: 依存関係破損が 3 個 [+3], 更新が 113 個 [-4]。
# aptitude upgrade
-bash: /usr/bin/aptitude: そのようなファイルやディレクトリはありません
# exit
logout
INIT: cannot execute "/sbin/getty"
INIT: cannot execute "/sbin/getty"
INIT: cannot execute "/sbin/getty"
INIT: cannot execute "/sbin/getty"
INIT: cannot execute "/sbin/getty"
INIT: cannot execute "/sbin/getty"
INIT: cannot execute "/sbin/getty"
INIT: cannot execute "/sbin/getty"
INIT: cannot execute "/sbin/getty"
INIT: cannot execute "/sbin/getty"
INIT: Id "1" respawning too fast: disabled for 5 minutes
INIT: no more processes left in this runlevel

どうもlibc関係みたいです。
こうなると何もできない。
回避方法はアップグレードしないこと。
とりあえずholdしとけばいい?
んで、いつ修正されるんだこれ。
こっちの人も同じ状況になってるんだけど、libcのバージョンが結構違うのよね。
うちは
2.13-16 -> 2.13-19
あちらでは
2.13-2 -> 2.13-3
何となくだけどこれ環境によってでるでないがありそう。
さすがにみんながこの状況に陥るならリリースされないだろうし。

追記
やはりバグレポート提出されていた。
2.13-20で治ったらしいけど怖いなー。
あとでバックアップして更新やってみるか。