2013年7月30日火曜日

MyNA会2013年7月に行ってきました

行ってきました。
昨日は無事でした。

http://atnd.org/events/40892

無事というのはアレです。
今年に入ってからジンクス的なものがあってですね、

  • MySQL Tech Tour Tokyoでオラクル青山へ行く
    • MySQLがサーバーごと壊れてアラートで帰る
  • MyNA会2013年3月でオラクル青山へ行く
    • 朝一でデータがぶっ壊れて午前中ずっとリカバリー
    • 38度近く熱が出てオーバーヒートしながら何かしゃべった
  • MySQL勉強会 in 大阪(第4回)
    • Ustで見てただけなのに発熱Again
オラクル青山に行くたびに何かアラートが、勉強会のたびに発熱が襲ってくるわけですが、今年も半分以上終わったところで初めて平穏でした。

代わりに今日、バックアップサーバーが壊れてリブートを繰り返し、俺のお腹も急降下ですけどな!orz

やっぱ呪われてるんだと思います。


で、やってきたネタLTなんですが、



チューニンガソン5の復讐 from yoku0825


ネタLTのくせに間が悪くてスベりまくり、その後のごはんで坂井さんにしんみり諭されました。精進します。。


中身の話はsmallpalaceさんがまとめてくれてました。すてき。
smallpalace's blog - myna会20130729にいってきた記録

performance_schemaすごく面白かったです。英語で話しかけられない自分のへたれっぷりにへこみました。奥野さんがナチュラルに「質問、日本語でも大丈夫ですよ」とか誘導しててカコヨカッタです。というかかじやまさんが始まってすぐどこかに飛び立って行ったのにすごくやられた感が。。リアルタイム通訳を期待していたのは俺だけではあるまい。。
きっといとーさんのベンチマークが火を噴いて(全てのenabled='No'だったら--performance-schema=0とそんなに変わらない? とか)、スパスパMySQLの席で発表されるんじゃないかと思います。煙草吸いながら聞きたいなー(棒

MySQLプロトコルは超俺得で俺は何も作りませんが色々遊ぼうと思います。OSC 2013 Tokyo/Fallで再演されるという話が出ていましたが定かではありません。

あと、SH2さんにアイスをおごることができたので、俺の夏はもう終わりかなと思います。


後は年を食うだけかな。。

MySQLサーバーのディスク容量減少アラートが飛んでくる前に

このビッグウェーブにいつ乗るの! 今でしょ!


元RX-7乗りの適当な日々
Linuxサーバがディスク容量不足になった!何か消さねば!ってなった時にどう対処するか

tagomorisのメモ置き場
Linuxサーバのディスク容量減少アラートが飛んできた!ってときにどう対処するか

iをgに変えるとorangeになることに気づいたoranieの日記
Cassandraサーバのディスク容量減少アラートが飛んできた!ってときにどう対処するか


…と思ってたらMySQLバージョンも既に出た。けどめげない。かぶらないように書きます。というかタイトルはかぶらないように変えました(つд`)

Y-Ken Studio
MySQLサーバのディスク容量減少アラートが飛んできた!ってときにどう対処するか


さてまず、MySQLで勝手に(?)増えるものといえば。

  1. データファイル(.MYD, .MYI, .ibd, ibdata1)
  2. バイナリーログファイル, リレーログファイル
  3. スローログファイル
  4. エラーログファイル
  5. テンポラリーファイル, テンポラリーテーブル
くらいかなあ。少なくとも俺が過去にDISKをあふれさせたことがあるのはこいつらくらいです。


1. データファイル

ウチの場合、取り敢えず一番増えるのは ほげほげ_history とか なんちゃら_logs とかそんな名前のテーブルです。最低限、1行あたりのサイズを押さえておく必要があります。

mysql> SHOW TABLE STATU LIKE 'hogehoge_logs'\G
*************************** 1. row ***************************
           Name: hogehoge_logs
         Engine: InnoDB
        Version: 10
     Row_format: Compressed
           Rows: 18
 Avg_row_length: 455
    Data_length: 8192
Max_data_length: 0
   Index_length: 32768
      Data_free: 0
 Auto_increment: 19
    Create_time: 2013-07-22 23:55:13
    Update_time: NULL
     Check_time: NULL
      Collation: ujis_japanese_ci
       Checksum: NULL
 Create_options:
        Comment:
1 row in set (0.00 sec)

Avg_row_lengthはデータ部分だけのサイズなので、(Data_length + Index_length) / Rowsでインデックス込みの1行あたりの値をとっときます。意外と大きいケースが多かったりするので。するので。

↑のテーブルだと(ちょっとデータ量が少なすぎて全くアテにならないとはいえ)1行当たり2.2KiBくらい、Create_timeから察するに1日の増加量は2.5行、万一(ひどい)サービスがバズってトラフィックが10倍になったとしても1日50KiBくらいですね。


というのを、information_schemaから全テーブル分ばっこ抜きます。

mysql> SELECT
    ->  TABLE_SCHEMA,
    ->  TABLE_NAME,
    ->  ENGINE,
    ->  SUM(((DATA_LENGTH + INDEX_LENGTH) / TABLE_ROWS) / TIMESTAMPDIFF(DAY,  CREATE_TIME, NOW())) AS 1d_size
    -> FROM
    ->  information_schema.tables
    -> WHERE
    ->         ENGINE IN ('InnoDB', 'MyISAM')
    ->  AND TABLE_SCHEMA NOT IN ('information_schema', 'mysql')
    -> GROUP BY
    ->  TABLE_SCHEMA, TABLE_NAME
    -> WITH ROLLUP;
+--------------+-------------------------+--------+----------------+
| TABLE_SCHEMA | TABLE_NAME              | ENGINE | 1d_size        |
+--------------+-------------------------+--------+----------------+
| xxxx         | hogehoge_logs           | InnoDB |   537.18032787 |
..
| xxxx         | NULL                    | InnoDB | 61917.19581370 |
| NULL         | NULL                    | InnoDB | 61917.19581370 |
+--------------+-------------------------+--------+----------------+

SUMもへったくれもない1d_sizeカラムにSUM()をつけているのは、WITH ROLLUPで最後に合計値を出すためです。
便利ですよWITH ROLLUP。滅多に使わないけど。
http://dev.mysql.com/doc/refman/5.6/en/group-by-modifiers.html

というわけで、このMySQL(検証用DBだけど)は1日あたり60KiBちょっと、バズって100倍来ても大丈夫ですね(にっこり)

information_schemaだし、飽くまで参考値にしかなりませんが、定常状態を知っておくのは大事だと思います。


2. バイナリーログファイル, リレーログファイル

データファイルより更に手抜きで引っこ抜きます。
大概の場合、--expire-logs-daysで過去何日分かに絞っていると思うので、それで割り算しちゃいます。

$ ls -l mysql-bin.* | awk '{i+=$5}END{print i}'
356928028

7日間で350MiBくらいなので50MiB/dayくらいですね。100倍バズるとちょっと大変かも。
リレーログも余裕を見てこれと同じだけ見込むことにしてます。
というわけで--log-slave-updatesつきの中間スレーブで100MiB/day。

もしイベントなんかの期間要因がバイナリーログの保存期間の中に含まれていて、そこは除外したいというのがあれば、mysqlbinlogでテキトーに引っこ抜きます。SQLデコードされる分容量が0%(増えない)~100%(2倍)くらいになっちゃうんですが、多少安全側に倒していると思って諦めます。

$ mysqlbinlog mysql-bin.* --start-datetime="2013-07-21 00:00:00" --stop-datetime="2013-07-22 00:00:00" | wc
  12213   59409  543939

540KiB/day。バラつきがあったんだなぁ。。どっちを採用するか却って悩むかも知れません。

【2013/07/30 13:24】
ちなみに、--binlog_format=mixedだと、LOAD DATA INFILEがROWモードで1行ずつロギングされるので--expire-logs-daysに関係なく瞬間的に結構な量になります。↑のばらつきはそうだったっぽいです。


3. スローログファイル

まあ、増える時は増えますよね! たまに気にしてあげてください。
あと、クエリーをまるっと書き出す性質上、DWH的な使い方をしててスローログ出てもいいからサブクエリーやJOINし放題、WHERE .. IN (..)に3000くらい定数が列挙してあるぜはははーなやつがあったりするとあっという間に太ります。

つーか、出ても気にしないんだったら切っとけ。。


4. エラーログファイル

意外と肥大化の原因になってるのが[Warning]で、コイツ、当然ながらエラーは返さないなれどエラーログには記録されるんですよね(--log-warnings=n でレベル指定。暗黙のデフォルトは1)

で、アプリから投げたSQLのWarningって意外と気にしてくれない人が多いので気が付くとぼこぼこぼこぼこぼこぼこぼこぼこ。。

しかも俺が最近よく見るWarningレベルのログって、ご丁寧にワーニングになったクエリーを書き出してくれる親切設計なので、 1 ク エ リ ー 8 K i B も あ る いじめのようなクエリーがごりごり書き出されてあっという間にエラーログが太ったことがありました。

このクエリーはスローログファイルもいじめました。もうやめて! MySQLのライフはゼロよ!


5. テンポラリーファイル, テンポラリーテーブル

これもうちょっと細分化すればよかったかも知れない。
Using filesortの時に使うテンポラリーファイル, Using temporaryの時に使う(かつ、Diskに固定化された)テンポラリーテーブル, 5.6のInnoDB Online Alter Table(--innodb_online_alter_log_max_size=nで制御、暗黙のデフォルトは128M)で使う更新ログっぽいやつは軒並みtmpdirに吐く。

特に前2つはtmpdirが/tmpのままだったりすると意外とあっさり食いきられてError:28(=No space left on device)をエラーログに吐いてSort Abortしたり。
クエリーがAbortされたあとは(一応)自動で消えはするものの、そのクエリーはエラーで返ることになる。で、大概テンポラリーテーブルのサイズがそもそもtmpdirにおさまってないのが問題なので、同じクエリーを投げればまあ再現する羽目に。。

あとはいわゆるフツーのALTER TABLEの時はdatadir(ALTER対象のテーブルのまどなり)にテンポラリーテーブルを作る。インデックスやカラムを追加する時は今のサイズにその新しい容量が乗っかるので、ALTER対象テーブルサイズよりちょっと大きめの量が余計に必要になるので注意。これがあふれてALTERがAbortされると、「俺の3時間を返せええええええ」ってなったりならなかったり。。


なんか終盤ぐだぐだになってますが、体感的にはMySQLのデータを破損させる一番の原因はDisk Fullなので、「そもそもアラートが㌧でこないように! ギリギリの運用イクナイ!」ということを主張するものであります。

おらにえさん、こんな感じでいいですかー?w

2013年7月29日月曜日

MySQL Proxyで認証をフックしようと悪戦苦闘(ユーザー名だけ書き換えはOK)

前回 の続き。
要件はこんな感じ。

  • ユーザー名に"+"が含まれていた場合、"+"とそれ以降の文字列を握りつぶす。
    • mysql -uroot+yoku0825 -p だったら、rootに変換してやる。
  • パスワードやその他のオプションは入力されたものを素通し。
  • クライアントはmysqlコマンドラインクライアントとは限らない。

取り敢えず判ったところまででは、
  • MySQL Proxy 0.8.3以降はto_response_packetにserver_capabilitiesの指定が必須になったっぽい。
  • server_capabilitiesに使える値の一覧はinclude/mysql_com.hに書いてある。
  • 取り敢えず ここ を参考にCLIENT_PROTOCOL_41(=512)とCLIENT_SECURE_CONNECTION(=32768)を設定したら、ユーザー名の握りつぶしは成功した。
$ cat ./proxy.lua
local password= assert(require("mysql.password"))
local proto= assert(require("mysql.proto"))

function read_auth()
  local c = proxy.connection.client
  local s = proxy.connection.server

  local proxy_user= c.username
  local mysql_user= string.match(c.username, "^(%w+)+")
  if not mysql_user then mysql_user= proxy_user end

  proxy.queries:append(1, proto.to_response_packet(
  {
    server_capabilities= 33280,
    username= mysql_user,
    response= c.scrambled_password
  }))

  return proxy.PROXY_SEND_QUERY
end

$ /usr/mysql/proxy/bin/mysql-proxy --proxy-address=127.0.0.55:3306 --proxy-backend-addresses=127.0.0.1:64055 --proxy-lua-script=/usr/mysql/proxy/proxy.lua --log-level=debug

$ mysql -h 127.0.0.55 -P 3306 -u root+yoku0825 -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 15
Server version: 5.5.32-log Source distribution

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> status
--------------
mysql  Ver 14.14 Distrib 5.6.12, for Linux (x86_64) using  EditLine wrapper

Connection id:          15
Current database:
Current user:           root@localhost
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         5.5.32-log Source distribution
Protocol version:       10
Connection:             127.0.0.55 via TCP/IP
Server characterset:    utf8
Db     characterset:    utf8
Client characterset:    utf8
Conn.  characterset:    utf8
TCP port:               3306
Uptime:                 2 days 19 hours 27 min 2 sec

Threads: 3  Questions: 77  Slow queries: 2  Opens: 36  Flush tables: 1  Open tables: 29  Queries per second avg: 0.000
--------------

mysql> SELECT current_user();
+----------------+
| current_user() |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)

よしよしよしよし。
しかしまあ、相変わらずパスワードとかいじろうとすると(to_response_packetでresponseを書き換えると)assertion `20 == challenge_len' failedになっちゃうんだよなぁ。。
そこはまた追って調べるとして、取り敢えずこれで他に情報をログする部分を書きましょうそうしましょう。

Wiresharkのプロトコルデコード機能を使ってMySQLのパケットを覗く

port 3306なら余計なことをしなくてもWiresharkが勝手にMySQLプロトコルとしてデコードしてくれるんだけど、残念ながら3306以外の場合は手動で設定してやらんといかん。

取り敢えずキャプチャー。
MySQLが浮いてるのはLinuxで、俺が使ってるのはWindows。

# tcpdump -i any -w /tmp/mysql55.cap port 64055
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
^C21 packets captured
42 packets received by filter
0 packets dropped by kernel

64055番ポートにMySQL 5.5.32が浮いているのでそれをキャプチャーしてみた。

$ mysql55 --protocol=tcp
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.5.32-log Source distribution

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql55>
mysql55>
mysql55>
mysql55> SELECT 'さんをつけろよデコ助野郎!';
+-----------------------------------------+
| さんをつけろよデコ助野郎!              |
+-----------------------------------------+
| さんをつけろよデコ助野郎!              |
+-----------------------------------------+
1 row in set (0.00 sec)

mysql55>
mysql55>
mysql55>
mysql55> exit
Bye

最近知ったんだけど、--protocol=tcp ってすると、わざわざ--host=127.0.0.1ってやらなくてもTCP/IP使うようになる(今更

で、まあ/tmp/mysql55.capを手元に持ってきてWiresharkに食わせる。




デコードされてないのでヘッダ以外は16進でしか表示されていないので、読みにくいことこの上ない。
ので、



テキトーなパケットを右クリックして"Decode As"を選択。




TransportタブでDecodeをMySQLにしてOK押下。




よし素敵。
画像びみょー。。

2013年7月24日水曜日

MySQL Proxyで認証をフックしようと悪戦苦闘(成功してない)

色々あって、MySQL ProxyでMySQLの認証パケットを書き換えたい。
具体的にはこんな感じ。

  • ユーザー名に"+"が含まれていた場合、"+"とそれ以降の文字列を握りつぶす。
    • mysql -uroot+yoku0825 -p だったら、rootに変換してやる。
  • パスワードやその他のオプションは入力されたものを素通し。
  • クライアントはmysqlコマンドラインクライアントとは限らない。

で、まあ取り敢えずソースコードに付属していたExampleのLuaスクリプトを覗いてみる。

https://github.com/cwarden/mysql-proxy/blob/master/examples/tutorial-scramble.lua

Lua読めないけど感じ的に、「user: replace, password: me」で認証パケットを投げると、「user: root, password: secret」に書き換えてバックエンドに投げてくれるような気配がする。
良いじゃない、素敵。

サンプルスクリプトだと書き換える先はテーブルで持ってるけど、これをユーザー名は正規表現で抽出してやって、パスワードは書き換えない方針にすればきっといける。


…と思ったのが1週間前、で、今まだ出来てない(´・ω・`)

$ /usr/mysql/proxy/bin/mysql-proxy --proxy-address=127.0.0.56:3306 --proxy-backend-addresses=127.0.0.1:64056 --proxy-lua-script=/usr/local/src/mysql-proxy-0.8.3/examples/tutorial-scramble.lua --log-level=debug
2013-07-24 18:38:24: (critical) plugin proxy 0.8.3 started
2013-07-24 18:38:24: (debug) max open file-descriptors = 8192
2013-07-24 18:38:24: (message) proxy listening on port 127.0.0.56:3306
2013-07-24 18:38:24: (message) added read/write backend: 127.0.0.1:64055

起動は問題なく。

$ mysql -h 127.0.0.56 -P 3306 -utpcc -ptest
Warning: Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 214
Server version: 5.6.12-log Source distribution

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> SELECT current_user();
+----------------+
| current_user() |
+----------------+
| tpcc@%         |
+----------------+
1 row in set (0.05 sec)

実在するユーザーで認証をかけるのも問題なし。
でも。

$ mysql -h 127.0.0.56 -P 3306 -ureplace -pme
Warning: Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'replace'@'localhost' (using password: YES)

え、ユーザー名すりかえられてない。。

for challenge "l-7mA=KCL7j3]Z,l^q>!\000" the client sent ",wョ。ア3礼P|ェ\
&濘\\m"
2013-07-24 18:45:20: (critical) network_mysqld_proto_password_check: assertion `20 == challenge_len' failed
2013-07-24 18:45:20: (debug) [network-mysqld.c:1134]: error on a connection (fd: -1 event: 0). closing client connection.

しかも認証パケットの長さがおかしいとか言われてる。。
バックエンドが5.6だからかなぁと思って5.5につないでみても同じ。
5.1, 5.0だとエラーメッセージがチャレンジコードの長さ云々じゃなくて.server_capabilities has to be setというのに変わるので云々。。

先は長そうだ。

2013年7月22日月曜日

mysqlコマンドラインクライアントの改変と社内LT

社内LT用にmysqlコマンドラインクライアントをネタ改変したものの、たぶん他所でやることもないと思うのでこっちに書いてみる。



やってることはシンプルに単なるネタ。
書き上げたパッチをMySQL 5.6.12に適用してやると、mysqlコマンドラインクライアントに"さん"をつけないと怒る様にできます。

ここから
$ cd mysql-5.6.12

$ wget https://gist.github.com/yoku0825/5932320/raw/d715a496707357a220e5ebde34866cc2af656686/decosuke.patch

$ patch -p0 < decosuke.patch
patching file client/mysql.cc

$ cmake .
..

$ make mysql
..
Scanning dependencies of target mysql
[100%] Building CXX object client/CMakeFiles/mysql.dir/mysql.cc.o
Linking CXX executable mysql
[100%] Built target mysql

使い方。
"さん"をつけずにログインすると(mysqldは何でも良い)「さんをつけろよデコ助野郎!」と言われます。
exitくらいは通すようにしとくべきでしたが、exitですら言われます。

mv, cp, ln(ハードリンクでもシンボリックリンクでも)で"さん"をつけて、実行ファイル名を"mysql-san"にするとまともに動きます。

ただし、"さん"を間違って"mysql-sun"にするとやっぱり怒られます。


$ client/mysql -uroot -p -S /usr/mysql/5.6.12/data/mysql.sock
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 46
Server version: 5.6.12-log Source distribution

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> status
_人人人人人人人人人人人人人人人_
> さんをつけろよデコ助野郎! <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄
mysql> 
mysql> ^DBye

$ cp -ip client/mysql client/mysql-sun

$ client/mysql-sun -uroot -p -S /usr/mysql/5.6.12/data/mysql.sock
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 47
Server version: 5.6.12-log Source distribution

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> status
_人人人人人人人人人人人人人人人人人人_
> 黙れ小僧! お前にSunを救えるか! <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄
mysql> ^DBye

$ cp -ip client/mysql client/mysql-san

$ client/mysql-san -uroot -p -S /usr/mysql/5.6.12/data/mysql.sock
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 48
Server version: 5.6.12-log Source distribution

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> status
--------------
client/mysql-san  Ver 14.14 Distrib 5.6.12, for Linux (x86_64) using  EditLine wrapper

Connection id:          48
Current database:
Current user:           root@localhost
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         5.6.12-log Source distribution
Protocol version:       10
Connection:             Localhost via UNIX socket
Server characterset:    utf8
Db     characterset:    utf8
Client characterset:    utf8
Conn.  characterset:    utf8
UNIX socket:            /usr/mysql/5.6.12/data/mysql.sock
Uptime:                 3 days 5 hours 27 min 13 sec

Threads: 1  Questions: 599170  Slow queries: 0  Opens: 121  Flush tables: 1  Open tables: 72  Queries per second avg: 2.148
--------------

楽しんでください。

2013年7月10日水曜日

TokuDBをCentOS 6.3(以降?)で動かしたい方へ

エラーログにこんなんが出て、どうもPluginのInitに失敗していた。

130710 10:24:52 Percona XtraDB (http://www.percona.com) 5.5.30-tokudb-7.0.1-29.3 started; log sequence number 1597945
Transparent huge pages are enabled, according to /sys/kernel/mm/redhat_transparent_hugepage/enabled
130710 10:24:52 [ERROR] Plugin 'TokuDB' init function returned error.
130710 10:24:52 [ERROR] Plugin 'TokuDB' registration as a STORAGE ENGINE failed.
130710 10:24:52 [Warning] /usr/percona/5.5.30_tokudb/bin/mysqld: unknown variable 'loose-innodb-buffer-pool-dump-at-shutdown=1
'
130710 10:24:52 [Warning] /usr/percona/5.5.30_tokudb/bin/mysqld: unknown variable 'loose-innodb-buffer-pool-load-at-startup=1'
130710 10:24:52 [ERROR] Unknown/unsupported storage engine: TokuDB
130710 10:24:52 [ERROR] Aborting

取り敢えず、

# echo never > /sys/kernel/mm/redhat_transparent_hugepage/enabled

で起動するようになった。

https://groups.google.com/forum/#!topic/tokudb-user/d3CujW353_4


transparent hugepageが何であるかは↓を読んでなんとなく心で感じることにした。

http://blog.goo.ne.jp/u1low_cheap/e/72a7c5528858debe4e34df83430c480e


取り敢えず同じところでハマった誰かに届け!

好きなスクリプト叩いて情報を持ってくるinformation_schemaプラグイン作った

別にスクリプトじゃなくて何でも動くけど。。

https://github.com/yoku0825/scripting_i_s

scripting_i_s.ccの中のI_S_SCRIPTのマクロを任意の実行ファイルに変えてやれば、そいつを実行した出力を空白セパレートでinformation_schema.scripting_i_sテーブルから参照できるようになっていたり。MySQL 5.5.32では動作確認済み。

取り敢えずこんな感じでいく。

$ cat /tmp/test.pl
#!/bin/bash
/bin/awk '{print $1, $2}' /proc/`pidof mysqld`/io >&2

mysql55> INSTALL PLUGIN scripting_i_s SONAME 'scripting_i_s.so';
Query OK, 0 rows affected (0.01 sec)

mysql55> SELECT * FROM information_schema.scripting_i_s;
+------------------------+---------+
| name                   | value   |
+------------------------+---------+
| rchar:                 | 9806796 |
| wchar:                 | 136035  |
| syscr:                 | 5898    |
| syscw:                 | 429     |
| read_bytes:            | 24576   |
| write_bytes:           | 311296  |
| cancelled_write_bytes: | 233472  |
+------------------------+---------+
7 rows in set (0.02 sec)

test.plの中身がPerlじゃないのは気にしない。

取り敢えずSuper_privが必要なようにはしてあるけど、mysqldの実行ユーザーで叩けるスクリプトは何でも叩くダメ仕様。md5をマクロでハードコードしておいて、実行都度md5判定させようとしたけれど、C力の低さで失敗し続けたので諦めた。

もうちょこちょこいじりたいなー。


【2013/07/10 15:36】
スクリプトから戻ってくる結果が1行64KiBを超えると多分セグフォる(キリ

2013年7月2日火曜日

MySQL Utilitiesのmysqlusercloneを試す

先日rpmで突っ込んだMySQL Utilitiesのmysqlusercloneを試してみる。

http://dev.mysql.com/doc/workbench/en/mysqluserclone.html

やってくれることは、既存のユーザー情報をコピーして新しいユーザーを作ってくれる。
CREATE USER .. LIKE ..(こんな構文ないけど、ニュアンスで感じて下さい)みたいな感じ。

取り敢えず、--sourceでユーザーのコピー元MySQLに`ログインするためのDSN'、--destinationでユーザーのコピー先MySQLに`ログインするためのDSN'を指定する。

ドキュメントには特に書いてないけど、--sourceの暗黙のデフォルトはroot@localhost:3306、--destinationを省略すると--sourceと同じコネクションの中でGRANTを叩く。

my.cnfの[client]セクションは読んでる。他のところはよく判らない。

基本的な動作。

$ mysqluserclone --source root@localhost:/usr/mysql/5.6.12/data/mysql.sock tpcc@% tpcc2@localhost
# Source on localhost: ... connected.
# Cloning 1 users...
# Cloning tpcc@% to user tpcc2@localhost
# ...done.

/usr/mysql/5.6.12/data/mysql.sockを使ってroot@localhostでログインして、tpcc@%というユーザーの情報をコピーして、tpcc2@localhostというユーザーを作る。
ジェネラルログはこんな感じ。

$ less general.log
130702 13:00:30    17 Connect   root@localhost on
                   17 Query     SET NAMES 'latin1' COLLATE 'latin1_swedish_ci'
                   17 Query     SET @@session.autocommit = OFF
                   17 Query     SHOW VARIABLES LIKE 'READ_ONLY'
                   17 Query     COMMIT
                   17 Query     SHOW VARIABLES LIKE 'VERSION'
                   17 Query     COMMIT
                   17 Query     SELECT * FROM mysql.user WHERE user = 'tpcc' and host = '%'
                   17 Query     COMMIT
                   17 Query     SELECT * FROM mysql.user WHERE user = 'tpcc2' and host = 'localhost'
                   17 Query     COMMIT
                   17 Query     SELECT * FROM mysql.user WHERE user = 'tpcc2' and host = 'localhost'
                   17 Query     COMMIT
                   17 Query     SELECT CURRENT_USER()
                   17 Query     COMMIT
                   17 Query     SHOW GRANTS FOR 'tpcc'@'%'
                   17 Query     COMMIT
                   17 Query     SELECT * FROM mysql.user WHERE user = 'tpcc2' and host = 'localhost'
                   17 Query     COMMIT
                   17 Query     CREATE USER 'tpcc2'@'localhost'
                   17 Query     GRANT USAGE ON *.* TO 'tpcc2'@'localhost'
                   17 Query     SELECT * FROM mysql.user WHERE user = 'tpcc2' and host = 'localhost'
                   17 Query     COMMIT
                   17 Query     GRANT ALL PRIVILEGES ON `tpcc`.* TO 'tpcc2'@'localhost'

ユーザー情報。

mysql> SHOW GRANTS FOR tpcc@'%';
+-----------------------------------------------------------------------------------------------------+
| Grants for tpcc@%                                                                                   |
+-----------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'tpcc'@'%' IDENTIFIED BY PASSWORD '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29' |
| GRANT ALL PRIVILEGES ON `tpcc`.* TO 'tpcc'@'%'                                                      |
+-----------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

mysql> SHOW GRANTS FOR tpcc2@localhost;
+---------------------------------------------------------+
| Grants for tpcc2@localhost                              |
+---------------------------------------------------------+
| GRANT USAGE ON *.* TO 'tpcc2'@'localhost'               |
| GRANT ALL PRIVILEGES ON `tpcc`.* TO 'tpcc2'@'localhost' |
+---------------------------------------------------------+
2 rows in set (0.00 sec)

おっとっと。。パスワードは指定しないとコピーしてくれないのね。
黙って同じものにしてくれて良いのに(´・ω・`)


$ mysqluserclone --source root@127.0.0.1:3306 tpcc@% tpcc3:<password>@'127.0.0.1'
# Source on 127.0.0.1: ... connected.
# Cloning 1 users...
# Cloning tpcc@% to user tpcc3:test@127.0.0.1
# ...done.

$ less general.log
130702 13:05:16    21 Connect   root@localhost on
                   21 Query     SET NAMES 'latin1' COLLATE 'latin1_swedish_ci'
                   21 Query     SET @@session.autocommit = OFF
                   21 Query     SHOW VARIABLES LIKE 'READ_ONLY'
                   21 Query     COMMIT
                   21 Query     SHOW VARIABLES LIKE 'VERSION'
                   21 Query     COMMIT
                   21 Query     SELECT * FROM mysql.user WHERE user = 'tpcc' and host = '%'
                   21 Query     COMMIT
                   21 Query     SELECT * FROM mysql.user WHERE user = 'tpcc3' and host = '127.0.0.1'
                   21 Query     COMMIT
                   21 Query     SELECT * FROM mysql.user WHERE user = 'tpcc3' and host = '127.0.0.1'
                   21 Query     COMMIT
                   21 Query     SELECT CURRENT_USER()
                   21 Query     COMMIT
                   21 Query     SHOW GRANTS FOR 'tpcc'@'%'
                   21 Query     COMMIT
                   21 Query     SELECT * FROM mysql.user WHERE user = 'tpcc3' and host = '127.0.0.1'
                   21 Query     COMMIT
                   21 Query     CREATE USER 'tpcc3'@'127.0.0.1' IDENTIFIED BY PASSWORD '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29'
                   21 Query     GRANT USAGE ON *.* TO 'tpcc3'@'127.0.0.1'
                   21 Query     SELECT * FROM mysql.user WHERE user = 'tpcc3' and host = '127.0.0.1'
                   21 Query     COMMIT
                   21 Query     GRANT ALL PRIVILEGES ON `tpcc`.* TO 'tpcc3'@'127.0.0.1'

mysql> SHOW GRANTS FOR tpcc3@127.0.0.1;
+--------------------------------------------------------------------------------------------------------------+
| Grants for tpcc3@127.0.0.1                                                                                   |
+--------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'tpcc3'@'127.0.0.1' IDENTIFIED BY PASSWORD '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29' |
| GRANT ALL PRIVILEGES ON `tpcc`.* TO 'tpcc3'@'127.0.0.1'                                                      |
+--------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

どうせもとのパスワードが分からなくてもIDENTIFIED BY PASSWORD '*..'で同じパスワードはコピーできるんだから、クローン元ユーザーと同じパスワードを設定するようなオプションが欲しいなぁ。
取り敢えずこれを使って、スキーマ名のtypoでサービスを止めかけるという惨事は二度と起こさないで済むようにしたい。。orz

ちなみに量産もできるぽい。

$ mysqluserclone --source root@127.0.0.1:3306 tpcc@% tpcc10@'127.0.0.1' tpcc11@'127.0.1.1' tpcc12@'127.0.2.1'
# Source on 127.0.0.1: ... connected.
# Cloning 3 users...
# Cloning tpcc@% to user tpcc10@127.0.0.1
# Cloning tpcc@% to user tpcc11@127.0.1.1
# Cloning tpcc@% to user tpcc12@127.0.2.1
# ...done.

ますますパスワードのコピーが欲しい。。

2013年7月1日月曜日

MySQL 5.6のCHANGE MASTER TOで出るようになったワーニング

MySQL 5.5までは何も出なかったけど、MySQL 5.6で追加されたワーニング。

mysql56> CHANGE MASTER TO MASTER_HOST= 'localhost', MASTER_PORT= 64055, MASTER_USER= 'replicatior', MASTER_PASSWORD= 'xxxx', MASTER_LOG_FILE= 'bin.000001', MASTER_LOG_POS= 1;
Query OK, 0 rows affected, 2 warnings (0.06 sec)

mysql56> SHOW WARNINGS;
+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                                                                                                                        |
+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Note  | 1759 | Sending passwords in plain text without SSL/TLS is extremely insecure.                                                                                                                                         |
| Note  | 1760 | Storing MySQL user name or password information in the master.info repository is not secure and is therefore not recommended. Please see the MySQL Manual for more about this issue and possible alternatives. |
+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

shell> cat data/master.info
23
bin.000001
4
localhost
replicatior
xxxx
64055
60
0





0
1800.000

0

86400


0

1759は読んだそのまま、パスワードがSSL使わずにマスターに送信されてるぞ、というNote。

1760は、CHANGE MASTER TOでUSER_NAMEとUSER_PASSWORDを指定するとmaster.info(master_info_repository= TABLEならmysql.slave_master_info)に平文で格納されるから危ういぞ、というNote。

どうすればこれが出なくなるかというと、START SLAVEで指定するようにする。

//
mysql56> CHANGE MASTER TO MASTER_HOST= 'localhost', MASTER_PORT= 64055, MASTER_LOG_FILE= 'bin.000001', MASTER_LOG_POS= 1;
Query OK, 0 rows affected (0.04 sec)

mysql56> START SLAVE USER= 'replicator' PASSWORD= 'xxxx'; --コンマ要らなかったり、MASTER_USERじゃなかったり。
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql56> SHOW WARNINGS;
+-------+------+------------------------------------------------------------------------+
| Level | Code | Message                                                                |
+-------+------+------------------------------------------------------------------------+
| Note  | 1759 | Sending passwords in plain text without SSL/TLS is extremely insecure. |
+-------+------+------------------------------------------------------------------------+
1 row in set (0.00 sec)

shell> cat data/master.info
23
bin.000001
4
localhost


64055
60
0





0
1800.000

0

86400


0

当然、master.infoにUSERとPASSWORDを保存しなくなるので、mysqldを再起動すると

2013-07-01 19:39:46 16508 [ERROR] Slave I/O: Fatal error: Invalid (empty) username when attempting to connect to the master server. Connection attempt terminated. Error_code: 1593
2013-07-01 19:39:46 16508 [Note] Slave I/O thread killed while connecting to master
2013-07-01 19:39:46 16508 [Note] Slave I/O thread exiting, read up to log 'bin.000001', position 4

こうなる。

まあ、好き好きかな。。


【2013/07/01 19:49】
マニュアルへのリンク忘れてた。。
http://dev.mysql.com/doc/refman/5.6/en/start-slave.html

【2013/07/02 10:19】
このNoteわかりにくいから変えようぜ、というBugsはこちら。
http://bugs.mysql.com/bug.php?id=68602