FAT47の底辺インフラ議事録

学んだことのメモ帳です

nginxでLDAP認証いれたらめっちゃ遅くなった話

静的コンテンツ配信の為だけのサーバでnginxを利用。
公開前のサーバだったのでLDAPの認証をかけて確認したところ、

cssとかjsとか画像ファイルとかの静的ファイルの応答時間が10秒かかって、
HTTPステータスコード000になるという状態になった。

/var/log/nginx/access.log

24**:****: - hoge_fuga [30/Jul/2014:13:53:48 +0900] "GET /pc/ HTTP/1.1" 200 2244 "http://[24**:****:]/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko Firefox/28.0" "-" 0.005
24**:****: - hoge_fuga [30/Jul/2014:13:53:50 +0900] "GET /img/header.png HTTP/1.1" 000 0 "http://[24**:****:]/pc/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko Firefox/28.0" "-" 10.002

nginxでLDAP認証いれた設定
/etc/nginx/nginx.conf

http { の中に
    ldap_server nd {
    url ldap://hogehoge-ldap.jp/ou=nd,dc=fugafuga,dc=co,dc=jp?uid?sub;
    require valid_user;
    }

server { の中に
    auth_ldap "LDAP";
    auth_ldap_servers nd;

LDAP認証を外したり、.httpasswdファイルを置いたBasic認証だと上記の状況にはならなかった。

nginx-auth-ldapソースコードには10000ms(10秒)のタイムアウト指定されていた
ngx_http_auth_ldap_module.c

ログ上の10秒後に応答帰ってくるのはこれが原因ぽい。

そしてこちらを見ると以下の様な設定がnginxで必要。
Module does no result-caching... slows down all web requests?


これがないとすべてのリクエストにLDAPの認証が毎回走ってしまうようだ。

auth_ldap_cache_enabled on;
auth_ldap_cache_expiration_time 10000;
auth_ldap_cache_size 1000;

auth_ldap_cache_expiration_timeとauth_ldap_cache_sizeに関しては、デフォルト値の設定があるようなので指定しなくても動作しそう。

なので、設定ファイルのhttp部に追加する。
/etc/nginx/nginx.conf

http {
.
.
.
    auth_ldap_cache_enabled on;

ログ確認

24**:****: - hoge_fuga [30/Jul/2014:13:55:45 +0900] "GET /pc/ HTTP/1.1" 200 2244 "http://[24**:****:]/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko Firefox/28.0" "-" 0.001
24**:****: - hoge_fuga [30/Jul/2014:13:55:45 +0900] "GET /img/header.png HTTP/1.1" 200 229015 "http://[24**:****:]/pc/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko Firefox/28.0" "-" 0.003

やったぜ速いぜ!

今までApache+LDAPでこの問題に遭遇したことなかったけど、
確認してみるとApacheではデフォルトでLDAPのキャッシュ有効になっていたようだ。
http://httpd.apache.org/docs/2.4/mod/mod_ldap.html#ldapopcacheentries


Apache大好き。

online-schema-changeを過信していたら痛い目をみた話

先日記事に書いたように、無停止のALTER文実行では
Percona-ToolkitのOnline-schema-changeを利用しています。
無停止でALTERできるPercona-Toolkitのonline-schema-change

オンラインでのカラム追加
私が担当しているサービスでは、ALTER文実行時にレプリケーションの遅延を出来るだけ発生させたくないので、
以下の様な手順でOnline-schema-changeを実行しています。

(1) スレーブ全台でOnline-schema-changeの実行
(2) マスターでOnline-schema-changeの実行(--set-vars="sql_log_bin=0"のオプション指定)

"sql_log_bin=0"オプションをつけて実行すると、binlogを出さずに実行できるので、
マスターで実行してもそのクエリはスレーブにレプリケーションされません。

この手順でINDEXの追加やカラムの追加などを実行していました。

事故の発生
いつものように、スレーブでonline-schema-change実行後、マスターで実行させました。
すると、一斉にアラートメールが。。。
スレーブ全台がエラーでレプリケーション停止してました。

Last_SQL_Error: Error executing row event: 'Table 'hoge._user_new' doesn't exist'
 Replicate_Ignore_Server_Ids:

事故の概要
"sql_log_bin=0"オプションを指定して実行したマスターDBでの作業時に、
なぜかトリガーの作成がスレーブにレプリケーションされて、
スレーブ側で存在しないテーブルへ更新が走るようになりエラーで停止しました。

そもそも、Online-Schema-Changeの仕組みとしては、先日記事に書いたとおり

online-schema-changeの仕組み
1. 対象テーブルと同じ構造をした作業用テーブルを作成する
2. 作業用テーブルに変更するALTER文を適用する
3. 3つトリガーを作成して、対象テーブルへの挿入・削除・更新が作業用テーブルに反映されるようにする
4. 対象テーブルから作業用テーブルへデータをコピーしてくる
5. RENAMEして対象テーブルと作業用テーブルを入れ替える
6. 入れ替え後の古いテーブルとトリガーを削除する

http://d.hatena.ne.jp/fat47/20140418/1397811745

このようになっています。
この(3)での処理がなぜかスレーブにも伝搬して、

Last_SQL_Error: Error executing row event: 'Table 'hoge._user_new' doesn't exist'
 Replicate_Ignore_Server_Ids:

このhoge._user_newテーブルへの更新がスレーブで走るようになってしまいました。

発生した環境
バージョン
DBマスター

OS CentOS5.4
DB MySQL5.5.24
Percona-Toolkit 2.2.7-1

DBスレーブ

OS CentOS6.2
DB MySQL5.5.24
Percona-Toolkit 2.2.7-1

発行したSQL

ALTER TABLE `user` ADD COLUMN fuga int(10) NOT NULL DEFAULT '0' COMMENT 'fugafuga';

対象テーブルのデータ件数

select count(*) from user;
+----------+
| count(*) |
+----------+
| 18476032 |
+----------+
1 row in set (9.09 sec)

検証環境でいろいろ試してみた
本番データを入れて検証環境で試してみました。
ちなみに、今回データ数の少ないステージング環境で事前に試していましたが、そちらの動作では問題ありませんでした。

エラー出て失敗したパターン
■DBMのOSバージョンを入れ替える
DBMをCentOS6.2、DBSをCentOS5.4に

MySQLのバージョンを上げてみる
MySQL5.5.24から5.5.34に

■Percona-Toolkitのバージョン下げてみる
他サービスで動作実績のある2.2.6に

■カラム追加ではなくてINDEX追加にして実行してみる


エラー出ずに実行完了したパターン
■別のテーブルにカラム追加してみる

■他サービスで実行成功したテーブル(今回のテーブルよりデータ量2倍)で確認してみる。
他サービスのテーブルをdumpして検証環境に挿入して実行


とりあえず結果
一部の条件を満たすテーブルでのみバグが発生する
でも、一部の条件がわからない…。なんだろう。。。

今後の対策
スレーブ側で作業テーブルがないためエラーになってしまうので、
スレーブ実行後に事前に作業テーブル(_テーブル名_new)を作成しておけば、仮にスレーブ側で
トリガーが作成されてしまってもエラーでレプリ停止することはない。
マスターで実行完了後に、スレーブで作成した作業テーブルをDROPする。

最後に
怖い作業やるときは、事前に本番と同様の環境で動作チェックすること!
本番に近いデータ量じゃないと再現しないこともある!



_| ̄|● サービス停止させて、本当に本当に申し訳ありませんでした。

無停止でALTERできるPercona-Toolkitのonline-schema-change

MySQL5.5をまだまだ絶賛利用中な私です。
サービスを運用しているとINDEX追加やカラム追加を行いたい要望が多々発生します。
それも無停止で。

MySQL5.6からは無停止でINDEX追加やカラム追加ができるオンラインDDLが実装されました。
カラム追加はまだ色々制約があるみたいですが…。
http://dev.mysql.com/doc/refman/5.6/en/innodb-create-index-overview.html

pt-online-schema-change
MySQL5.5でも似たようなことをやりたいので、
有名な「Percona-Toolkit」に同梱されているpt-online-schema-changeを利用しています。
http://www.percona.com/software/percona-toolkit

通常はロックが掛かってしまうALTER TABLEをロックなしで実行できるようになるツールです。
今までカラム追加の為に行っていた短時間のメンテナンスが必要なくなります。

online-schema-changeの仕組み
このような流れで実現されています。

1. 対象テーブルと同じ構造をした作業用テーブルを作成する

2. 作業用テーブルに変更するALTER文を適用する

3. 3つトリガーを作成して、対象テーブルへの挿入・削除・更新が作業用テーブルに反映されるようにする

4. 対象テーブルから作業用テーブルへデータをコピーしてくる

5. RENAMEして対象テーブルと作業用テーブルを入れ替える

6. 入れ替え後の古いテーブルとトリガーを削除する


インストール方法

yum install perl-DBD-MySQL perl-Time-HiRes perl-IO-Socket-SSL
wget http://www.percona.com/downloads/percona-toolkit/2.2.7/RPM/percona-toolkit-2.2.7-1.noarch.rpm
rpm -ivh percona-toolkit-2.2.7-1.noarch.rpm

利用方法

/usr/bin/pt-online-schema-change --execute --set-vars="SET VARIABLES" --alter="xxxxxx" h=HOSTNAME,D=DATABASE,t=TABLE_NAME,u=USER
--set-vars= SET hoge〜のようにオプション値指定したい時に
--alter= ALTER文の中身を書く
h= 接続先DBホスト
d= DB名
t= テーブル名
u= DBユーザ名

例えば以下の様な操作をしたい場合は、

mysql -uroot -h localhost
use hoge;
set sql_log_bin=0;
alter table hoge_table engine=InnoDB;

このようなコマンドになります。

/usr/bin/pt-online-schema-change --execute --set-vars="sql_log_bin=0" --alter="engine=InnoDB" h=localhost,D=hoge,t=hoge_table,u=root

利用時の注意点
■テーブルコピーを伴うのでIOとCPUかなり食う
■本番と同等スペックの検証環境で確認するべき
■普通にALTER打つよりは遅い
レプリケーション組んでいる時に普通に実行するとレプリ遅延が発生する
■Ctrl + Cで途中で止めた場合は、トリガーと作業テーブルの削除が行われないのでゴミ掃除する
その際は絶対に先にトリガーを削除する。テーブル消してしまうとエラーになる。


レプリ遅延回避の方法
プロダクトによっては、レプリ遅延の発生を許容できる作りになっていない場合も有ると思います。
オンラインでカラム追加を行った時に、絶対にスレーブのレプリケーション遅延を発生させたくない場合は、
以下の様な手順でレプリ遅延の発生を回避できます。

1. 先にスレーブ全台でonline-schema-changeを実行する。その際のオプションとして--set-vars="sql_log_bin=0"で変更binlogに出さないようにする。

2. スレーブ全台で完了後、マスターでonline-schema-changeを実行する。この時も--set-vars="sql_log_bin=0"を忘れずに。


※カラム追加などでテーブル構造を変更した場合、INSERTやUPDATEのクエリの書き方によってはアプリケーション側でエラー出る可能性もあるので、
その辺考慮しましょう。INDEX追加とかなら多分大丈夫です。


仕組みを理解した上で利用するには便利なツールなので、
みなさんガンガンつかっていきましょう。

MySQLでトランザクションの4つの分離レベルを試す

トランザクションとは
1つの作業単位として扱われるSQLクエリの集まりです。
複数のUPDATEやINSERTをひとつの集まりとして、
それらのクエリがすべて適用できた場合のみデータベースに反映します。
ひとつでも適用に失敗したクエリがあった場合は、そのまとまりすべてのクエリの結果は反映しません。

ACID特性
トランザクション処理に求められる4つの特性です。

原子性 (Atomicity)
トランザクションに含まれる手順が「すべて実行されるか」「すべてされないか」のどちらかになる性質。

一貫性 (Consistency)
どんな状況でもトランザクション前後でデータの整合性が矛盾なく保たれる性質。

分離性 (Isolation)
トランザクション実行中は、処理途中のデータは外部から隠蔽されて他の処理に影響を与えない性質。

永続性 (Durability)
トランザクションが完了したら、システムがクラッシュしてもデータが消失することがない性質。

分離レベル
MySQLに限らずSQL規格に則したデータベースでは4つの分離レベルを定義していて、
トランザクションの内外で見える変更と見えない変更のレベルを設定できます。
一般的に分離レベルが低いほど処理の並行性が高くなり処理速度向上が期待できますが、
その分データの不整合などのリスクが発生します。

READ UNCOMMITTED
一番低い分離レベルです。
コミットされていないトランザクションの結果が他のトランザクションから見える設定です。
特にパフォーマンスが優れているわけではないので、使用されることは滅多にないそうです。
コミット前のデータを読み取ることはダーティリードと呼ばれています。

上図では、トランザクション1が商品の売上をINSERT処理している途中で、トランザクション2で
商品価格を800円に変更をしています。このトランザクション2の値はROLLBACKされたら、
値が戻る可能性もある非常に不安定な値となっています。

READ COMMITTED
多くのデータベースシステム(OraclePostgreSQLSQL Server)でデフォルトの分離レベルになっています。
この分離レベルで見える値は、このトランザクションが開始されたときに既にコミットされている値だけで、
このトランザクション内の値もコミットするまで他からは見えない状態になっています。

分離レベルREAD UNCOMMITTEDで発生していたダーティリードは発生しません。
トランザクション2の値がコミットされるまでは、変更前の値を参照しつづけます。

しかしREAD COMMITTEDでは、次のような順番でSQLが発行された場合この状況が発生する可能性があります。

トランザクション1のSQL:1で取得される商品番号111の価格は400円ですが、
SQL:3で取得される商品の価格は800円になります。
このようにトランザクション1を実行中にトランザクション2の処理が完了してしまい、
トランザクション内で同じ値を参照しているのに数値が変わる現象をファジーリード(またはノンリピータブルリード)と呼びます。
同じ問い合わせを2回繰り返しても、同じ結果になるとは保証できないということです。

REPEATABLE READ
MySQLのデフォルトの分離レベルです。
なぜMySQLだけがREPETABLE READをデフォルトにしているのかわからないので、どなたか詳しい人教えて下さい。
この分離レベルはトランザクション内が読み取る値が、そのトランザクション内では同じに見える事が保障されます。

分離レベルREAD COMMITTEDで発生していたファジーリードは発生しません。
トランザクション1で参照される価格の値は、トランザクション1が開始された時点の価格を参照し続けるので
何度問い合わせをしても同じ値となります。

しかしREPEATABLE READもある条件によっては問題が発生する可能性があります。

トランザクション1は今までと同じように売上げた商品をテーブルにINSERTしています。
その途中で、今日1日の売上価格を計算しているトランザクション2の処理が開始されます。
トランザクション2のSQL:Aでは対象の売上件数は10件で価格の合計計算を行います。
その後にトランザクション1の処理が完了し変更がコミットされ、トランザクション2のSQL:BでCOUNTをすると
レコード数は11件となり、ひとつのトランザクション内で対象レコード数が異なってしまいます。
トランザクション中に幻影のように新しい行が現れる事から、ファントムリードと呼ばれています。
MySQLのストレージエンジンInnoDBでは、MVCC(MultiVersion Concurrency Control)という仕組みで
ファントムリードを防いでいます。
ここはまだいまいち理解できてないので、後ほど調べます。

SERIALIZABLE
最も高い分離レベルです。
複数トランザクションSQLが入り混じらないように、強制的にトランザクションを順序付けて処理します。
今まで出てきたすべての問題は発生しませんが、この分離レベルは読み取るすべての行にロックをかけます。
ロック競合が多発することになるのであまりこのレベルが使用されることはありません。


分離レベルと問題の関係

分離レベル ダーティリード ファジーリード ファントムリード 読み取りロック
READ UNCOMMITTED Yes Yes Yes No
READ COMMITTED No Yes Yes No
REPEATABLE READ No No Yes No
SERIALIZABLE No No No Yes


実際にMySQLで分離レベルの問題を発生させてみる

テーブルの作成

mysql> use test;
mysql> create table level_test(id INT(11) NOT NULL PRIMARY KEY,user_name varchar(32) not null );
Query OK, 0 rows affected (0.14 sec)

mysql> desc level_test;
+-----------+-------------+------+-----+---------+-------+
| Field     | Type        | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| id        | int(11)     | NO   | PRI | NULL    |       |
| user_name | varchar(32) | NO   |     | NULL    |       |
+-----------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

テストデータ挿入

mysql> insert into level_test values (1, 'hoge');
mysql> select * from level_test;
+----+-----------+
| id | user_name |
+----+-----------+
|  1 | hoge      |
+----+-----------+
1 row in set (0.00 sec)

ストレージエンジン確認
トランザクションを利用できるInnoDBになっているか。

mysql> select table_name, engine from information_schema.tables where table_schema = "test";
+------------+--------+
| table_name | engine |
+------------+--------+
| level_test | InnoDB |
+------------+--------+
1 row in set (0.00 sec)

トランザクション分離レベルの確認

mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)

MySQLのデフォルトのREPETABLE READになっています。


ダーティリード
READ UNCOMMITTEDで確認します。
※端末を2つ立ち上げます。

mysql1> SET SESSION TRANSACTION ISOLATION LEVEL read uncommitted;
mysql2> SET SESSION TRANSACTION ISOLATION LEVEL read uncommitted;

mysql1> select @@tx_isolation;
+------------------+
| @@tx_isolation   |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set (0.00 sec)

mysql2> select @@tx_isolation;
+------------------+
| @@tx_isolation   |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set (0.00 sec)

myqsl1> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql1> UPDATE level_test SET user_name = 'fuga' WHERE id = 1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

myqsl2> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql2> SELECT * FROM level_test;
+----+-----------+
| id | user_name |
+----+-----------+
|  1 | fuga      |
+----+-----------+
1 row in set (0.00 sec)

コミット前の変更(hoge→fuga)が別トランザクションから参照できている!


ファジーリード(アンリピータブルリード)
READ COMMITTEDで確認します。
※うまく分離レベルを変更できない事があったのでmysql端末を立ち上げなおして下さい。

mysql1> SET SESSION TRANSACTION ISOLATION LEVEL read committed;
Query OK, 0 rows affected (0.00 sec)

mysql2> SET SESSION TRANSACTION ISOLATION LEVEL read committed;
Query OK, 0 rows affected (0.00 sec)

mysql1> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set (0.00 sec)

mysql2> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set (0.00 sec)

mysql1> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql1> UPDATE level_test SET user_name = 'fuga' WHERE id = 1;

mysql2> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql2> SELECT * FROM level_test WHERE id = 1; 
+----+-----------+
| id | user_name |
+----+-----------+
|  1 | hoge      |
+----+-----------+
1 row in set (0.00 sec)

mysql1> COMMIT;

mysql2> SELECT * FROM level_test WHERE id = 1;
+----+-----------+
| id | user_name |
+----+-----------+
|  1 | fuga      |
+----+-----------+
1 row in set (0.00 sec)

トランザクション2内での値が変わっている!


ファントムリード
前述のとおりInnoDBはREPEATABLE READでファントムリードが起きないため、
READ COMMITTEDで確認します。

mysql1> SET SESSION TRANSACTION ISOLATION LEVEL read committed;
Query OK, 0 rows affected (0.00 sec)

mysql2> SET SESSION TRANSACTION ISOLATION LEVEL read committed;
Query OK, 0 rows affected (0.00 sec)

mysql1> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set (0.00 sec)

mysql2> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set (0.00 sec)

mysql1> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql2> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql2> SELECT COUNT(*) FROM level_test;
+----------+
| COUNT(*) |
+----------+
|        1 |
+----------+
1 row in set (0.01 sec)

mysql1> INSERT INTO level_test VALUES(2,"boo");

mysql1> COMMIT;

mysql2> SELECT COUNT(*) FROM level_test;
+----------+
| COUNT(*) |
+----------+
|        2 |
+----------+
1 row in set (0.00 sec)

トランザクション内2のCOUNTの結果が異なっている!


本当にREPEATABLE READでファントムリードが起きないか確認
端末を開き直す。
MySQLのデフォルトなのでREPEATABLE READになります。

mysql1> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)

mysql2> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)

mysql2> SELECT COUNT(*) FROM level_test;
+----------+
| COUNT(*) |
+----------+
|        1 |
+----------+
1 row in set (0.01 sec)

mysql1> INSERT INTO level_test VALUES(2,"boo");

mysql1> COMMIT;

mysql2> SELECT COUNT(*) FROM level_test;
+----------+
| COUNT(*) |
+----------+
|        1 |
+----------+
1 row in set (0.00 sec)

件数かわってない!!


今まであまり意識せずに利用してしまっていましたが、
分離レベルってものすごく重要ですね。

今回の内容は下記の書籍で解説されています。

実践ハイパフォーマンスMySQL 第3版

実践ハイパフォーマンスMySQL 第3版

冬の日2014〜ioDriveが壊れた日〜

ある日

ioDriveを積んでるMySQLスレーブサーバが突然の死

というか、レプリケーションが止まっていました。

サービスから参照されていないDBではあったので、
特に死んでいても問題にはなりませんでした。
今回つかっていたのはioDrive Duoです。

/var/log/messages確認
とりあえずシステムのログを確認してみると、

Jan 27 05:39:36 hoge-dbs kernel: fioinf HP 640GB MLC PCIe ioDrive Duo for ProLiant Servers 0000:09:00.0: groomer read had error -1024
Jan 27 05:39:36 hoge-dbs kernel: fioerr HP 640GB MLC PCIe ioDrive Duo for ProLiant Servers 0000:09:00.0: groomer error -1024 during read on eb 3408
Jan 27 05:39:36 hoge-dbs kernel: fioerr HP 640GB MLC PCIe ioDrive Duo for ProLiant Servers 0000:09:00.0:-  Due to simultaneous multiple device failur
es in EB 3408, the location of this
Jan 27 05:39:36 hoge-dbs kernel: fioerr HP 640GB MLC PCIe ioDrive Duo for ProLiant Servers 0000:09:00.0:-  error in the filesystem can not be easily 
determined. It is suggested that
Jan 27 05:39:36 hoge-dbs kernel: fioerr HP 640GB MLC PCIe ioDrive Duo for ProLiant Servers 0000:09:00.0:-  all data be checked to find the bad block 
and overwritten.
Jan 27 05:39:36 hoge-dbs kernel: fioerr HP 640GB MLC PCIe ioDrive Duo for ProLiant Servers 0000:09:00.0:-  For best results do not reboot the device 
until this is done.
Jan 27 05:39:36 hoge-dbs kernel: fioerr HP 640GB MLC PCIe ioDrive Duo for ProLiant Servers 0000:09:00.0: Groomer was unable to groom EB 3408 after 5 
retries: 5 sectors were ungroomed

なんだか怪しげなログがいっぱい出ていたので、

Fusion-IO ioDriveの障害例と調査方法


こちらの記事を参考にしながら確認してみます。

データ領域に書き込めるか確認
/dataにマウントしていたので、そこにデータが書き込めるかを確認したところ現状では書き込めていました。

fio-status確認

# fio-status
Found 2 ioDrives in this system with 1 ioDrive Duo
Fusion-io driver version: 2.3.10 build 110

Adapter: ioDrive Duo
        HP 640GB MLC PCIe ioDrive Duo for ProLiant Servers, Product Number:600282-B21 SN:xxxxx
        External Power: NOT connected
        PCIE Power limit threshold: 24.75W
        Sufficient power available: Unknown
        Connected ioDimm modules:
          fct0: HP 640GB MLC PCIe ioDrive Duo for ProLiant Servers, Product Number:600282-B21 SN:xxxxx
          fct1: HP 640GB MLC PCIe ioDrive Duo for ProLiant Servers, Product Number:600282-B21 SN:xxxxx

fct0    Attached as 'fioa' (block device)
        HP 640GB MLC PCIe ioDrive Duo for ProLiant Servers, Product Number:600282-B21 SN:xxxxx
        Located in slot 0 Upper of ioDrive Duo SN:xxxxx
        PCI:09:00.0
        Firmware v5.0.7, rev 107053
        322.55 GBytes block device size, 396 GBytes physical device size
        Sufficient power available: Unknown
        Internal temperature: 51.7 degC, max 56.1 degC
        Media status: Healthy; Reserves: 100.00%, warn at 10.00%

fct1    Attached as 'fiob' (block device)
        HP 640GB MLC PCIe ioDrive Duo for ProLiant Servers, Product Number:600282-B21 SN:xxxxx
        Located in slot 1 Lower of ioDrive Duo SN:xxxxx
        PCI:0a:00.0
        Firmware v5.0.7, rev 107053
        322.55 GBytes block device size, 396 GBytes physical device size
        Sufficient power available: Unknown
        Internal temperature: 52.2 degC, max 62.0 degC
        Media status: Healthy; Reserves: 100.00%, warn at 10.00%

なんだか正常に見えるなぁ。

※他にもログとか確認していたのですが、
OS再起動する前に記録取り忘れていたので割愛します。

OS再起動してみる
特にサービスで利用してないサーバだったのでOS再起動してみることに。
OSは無事上がりました。

# df -h
Filesystem            Size  Used Avail Use% マウント位置
/dev/sda3             547G  4.5G  515G   1% /
tmpfs                  16G     0   16G   0% /dev/shm
/dev/sda1             504M   63M  416M  14% /boot

さようなら、/dataちゃん・・・

もういっちょfio-status

# fio-status                                                                                                                       

Found 2 ioDrives in this system with 1 ioDrive Duo
Fusion-io driver version: 2.3.10 build 110

Adapter: ioDrive Duo
        HP 640GB MLC PCIe ioDrive Duo for ProLiant Servers, Product Number:600282-B21 SN:xxxxx
        External Power: NOT connected
        PCIE Power limit threshold: 24.75W
        Sufficient power available: Unknown
        Connected ioDimm modules:
          fct0: HP 640GB MLC PCIe ioDrive Duo for ProLiant Servers, Product Number:600282-B21 SN:xxxxx
          fct1: HP 640GB MLC PCIe ioDrive Duo for ProLiant Servers, Product Number:600282-B21 SN:xxxxx

fct0    Not attached
        HP 640GB MLC PCIe ioDrive Duo for ProLiant Servers, Product Number:600282-B21 SN:xxxxx
        Located in slot 0 Upper of ioDrive Duo SN:xxxxx
        PCI:09:00.0
        Firmware v5.0.7, rev 107053
        322.55 GBytes block device size, 396 GBytes physical device size
        Sufficient power available: Unknown
        Internal temperature: 51.7 degC, max 56.1 degC
        Media status: Healthy; Reserves: 100.00%, warn at 10.00%

fct1    Attached as 'fiob' (block device)
        HP 640GB MLC PCIe ioDrive Duo for ProLiant Servers, Product Number:600282-B21 SN:xxxxx
        Located in slot 1 Lower of ioDrive Duo SN:xxxxx
        PCI:0a:00.0
        Firmware v5.0.7, rev 107053
        322.55 GBytes block device size, 396 GBytes physical device size
        Sufficient power available: Unknown
        Internal temperature: 52.2 degC, max 62.0 degC
        Media status: Healthy; Reserves: 100.00%, warn at 10.00%

さようなら、fct0ちゃん・・・

試しにfct0にattach

# fio-attach /dev/fct0
Attaching: [====================] (100%) \
Error: failed to attach /dev/fct0. (4)

やっぱりダメ。


fct0ちゃんよ・・・永遠に・・・。

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::。:::::::::::::::::::::::::::::::::::::::::::::
:::::::::::::::::::::::::::::::::。::::::...... ...   --─-  :::::::::::::::::::: ..::::: . ..::::::::
:::::::::::::::::...... ....:::::::゜::::::::::..   (___ )(___ ) ::::。::::::::::::::::: ゜.::::::::::::
:. .:::::。:::........ . .::::::::::::::::: _ i/ = =ヽi :::::::::::::。::::::::::: . . . ..::::
:::: :::::::::.....:☆彡::::   //[||    」  ||]  ::::::::::゜:::::::::: ...:: :::::
 :::::::::::::::::: . . . ..: :::: / ヘ | |  ____,ヽ | | :::::::::::.... .... .. .::::::::::::::
::::::...゜ . .:::::::::  /ヽ ノ    ヽ__/  ....... . .::::::::::::........ ..::::
:.... .... .. .     く  /     三三三∠⌒>:.... .... .. .:.... .... ..
:.... .... ..:.... .... ..... .... .. .:.... .... .. ..... .... .. ..... ............. .. . ........ ......
:.... . ∧∧   ∧∧  ∧∧   ∧∧ .... .... .. .:.... .... ..... .... .. .
... ..:(   )ゝ (   )ゝ(   )ゝ(   )ゝ無茶しやがって… ..........
....  i⌒ /   i⌒ /  i⌒ /   i⌒ / .. ..... ................... .. . ...
..   三  |   三  |   三  |   三 |  ... ............. ........... . .....
...  ∪ ∪   ∪ ∪   ∪ ∪  ∪ ∪ ............. ............. .. ........ ...
  三三  三三  三三   三三
 三三  三三  三三   三三

Fusion ioのioDriveは結構な枚数と種類を1年以上使ってきていますが、
故障に出会ったのは始めてでした。

fio-bugreportとりました

Cassandra2.0のインストールと用語メモ

Cassandraとは
オープンソースの分散データベース。
元々Facebook社が開発し、現在はApache Software Foundationが開発中で、2013年12月現在の最新版は2.0.3です。

ノードがP2P通信でクラスタを組む非中央管理型のシステムであり、
スケーラビリティ、高可用性、耐障害性に優れていると
言われています。

以下勉強メモ
■Cassandraのインストール
■用語集

Cassandraのインストール
JDKインストール
OracleJDKをダウンロードしてくる
http://www.oracle.com/technetwork/java/javase/downloads/index.html

rpm -ivh /tmp/jdk-7u45-linux-x64.rpm

Cassandraダウンロード

wget http://ftp.tsukuba.wide.ad.jp/software/apache/cassandra/2.0.3/apache-cassandra-2.0.3-bin.tar.gz
tar zxvf apache-cassandra-2.0.3-bin.tar.gz 
mv apache-cassandra-2.0.3 /usr/local/
ln -s /usr/local/apache-cassandra-2.0.3 /usr/local/cassandra
mkdir -p /var/log/cassandra 
mkdir -p /var/lib/cassandra

起動

/usr/local/cassandra/bin/cassandra start

用語集
・memtable
メモリ上に常駐しているデータ構造。
コミットログに書き込まれた後にmemtableに書き込まれ、
オブジェクト数の閾値を超えるとSSTableにフラッシュされます。

・SSTable
Sorted String Tableの略で、ディスク上のデータ保存形式。
memtableの内容がSSTableにフラッシュされるとアプリケーションからは、
SSTableの内容は変更できなくなります。
すべての書き込みは追記で行われるため、書き込みパフォーマンスが良いです。
コンパクションによりSSTableのマージが可能。

・コミットログ
すべての書き込み操作を記録します。
コミットログ→memtable→SSTableの順。

・コンパクション
SSTableをマージすることでファイルサイズを小さくします。
Cassandraはすべての挿入、更新、削除が追記で記録されるためSSTableが肥大化しやすいので、
キーのマージや、カラム連結、トゥームストーンの削除などを行ってSSTableの物理データを小さくします。
コンパクションには2種類あって、
メジャーコンパクションとリードオンリーコンパクションがあります。
※違いがいまいちわかってないのであとで調べる。


・トゥームストーン
Cassandraはデータの削除が行われても、データの物理削除は行われません。
かわりにトゥームストーンと呼ばれる削除フラグを追加します。
メジャーコンパクション実行時に、このトゥームストーンがついたデータが破棄されます。

レプリケーションファクタ
パフォーマンスを犠牲にして一貫性をどれだけ得るかの項目。
後述の一貫性レベル参照。

・一貫性レベル
クラスタ内のいくつのレプリカが書き込み・読み込み成功すれば成功とみなすかを決定する。
ZERO

書き込み 非同期でバックグラウンドで書き込む。もっとも信頼性が低い。

ANY

書き込み 書き込み受付がヒント(ヒントハンドオフ)であっても、最低1つのノードで成功したとみなす


ONE

書き込み 書き込み操作がコミットログとmemtableを含む最低1つのノードに書き込まれたことを保証.1つのノードから返答があったら成功とみなす。
読み込み 最初に応答したノードが返答する

QUORAM

書き込み レプリケーションファクタで設定した数値によって操作するレプリカ数が変わる。(レプリケーションファクタ / 2) + 1の数のレプリカで成功が必要。レプリケーションファクタを6に設定していた場合、4つのレプリカが操作を受け付ける必要がある。サービス要件によって数値を指定する。
読み込み すべてのノードに検索をかけ、返答したノードのクオラムの中から最新タイムスタンプをもつ値を返す。クオラムは(ノード数/ 2) + 1

ALL

書き込み レプリケーションファクタで設定したすべてのノードで書き込みが成功しないといけない。最も高い一貫性レベルをもつがパフォーマンスは悪くなる
読み込み すべてのノードに検索をかけ、最新のタイムスタンプをもつ値を返す。ひとつのノードでも応答を返さなかったら読み込み失敗になる。


今日はここまで。
クラスタ設定とかコンパクションまわりもうちょっと調べる。

MySQL5.1からdumpしたデータをMySQL5.5に入れたらレプリ組んで死んだ日

MySQL5.1からdumpしたデータをMySQL5.5に入れてレプリを組んで、試しに更新クエリ流したらスレーブが死にました。

 Last_SQL_Error: Query caused different errors on master and slave.     Error on master: message (format)='Cannot load from mysql.%s. The table is probably corrupted' error code=1548 ; Error on slave: actual message='no error', error code=0. Default database: 'testtest2'. Query: 'drop database testtest2'

原因: mysql_upgradeやってなかった。

 mysql -uroot < /tmp/db.dump
 mysql_upgrade -uroot