GA

2014/08/31

#yapcasia 2014のおぼえがき

今年は1日目と2日目に参加しました。
内容レポートとかじゃなくて、感じたことメモ。

【1日目】
* 時間読み誤ってオープニング間に合わなかった…_| ̄|○

* すたじおさん の インフラエンジニア(狭義)は死んだ からスタート
 * 一時期元気がなさそうで心配でしたが、元気が戻ってきてそうでとても安心しました。

* けんじおじさんふしぎな感じのやつ。(タイトル全部書くのがちょっと恥ずかしいような)
 * 宇宙空間であった。。

* tokuhiromさんBDDのやつ
 * Test::Kantan 使いたい(Test::Moreですら手に余ってるけど)

* Rabisushiさんによる DBICのやつ
 * おお! という感じのツイートが多かったけど、クエリーをそんな方法でビルドするなんてそりゃあ闇も深いよとか違うことを考えていた。。

* 自分のセッションについてはこちら => 日々の覚書: WHERE狙いのキー、ORDER BY狙いのキー の話を #yapcasia でしてきました

* YappoさんJavaのやつ
 * Java書けないけど書いてみたくなった。なんてったってPerlとJavaは同じ言語だし。

* LT1日目
 * makamakaさん の完成度の高さには感動するしかない。

* 懇親会
 * kazeburoさんとちょっと話ができて、とても嬉しい。
 * あんちぽくんさん に初めて話しかけることに成功した(俺にとっては大きな一歩)ものの、多分忘れてらっしゃる(や、結構ご機嫌になったタイミングだったので)
 * Chiba.pmの面々と再会できてこれも嬉しい。


【2日目】
* kazeburoさんDockerのやつ
 * 使いどころないけど、取り敢えず遊んでみないと始まらないかなー。

* straceのやつ
 * うずらさんと同じ時間帯だって気付いてなかった…(超失礼)

* songmuさんPerlのヤーツ
 * Perlって色々できるんですね。。

* モリスさんそんなにビッグでもないやつ
 * 俺が見たセッションの中で一番感動した。
 * 全体的に松信さんぽさを感じた。
  * マシンガントーク(20分というのもあったろうけど)
  * 経験に裏打ちされた(であろう)鮮やかにポイントを押さえたトーク
  * というか、その界隈に詳しくない人間にもわかる明らかなカリスマ
 * ひとりですごい震えてた。

* LT2日目
 * いちばん刺さったのは NekogerugeさんTDD
  * 俺もほんとコレで、色んな人に色んな事を教えてもらって刺激もらって生きてる。
  * Twitter Driven Datsu-syoshinsya からの 出会い駆動コミュニティー活動 もオススメです :)


ホントすごい人が集まってすごい話がたくさんあって、(去年はそれほどそうとは思わなかったけど) YAPC最高! って感じでした。

ちなみに去年YAPCェ…ってなってたのは俺がほぼボッチだったせいだと思うので、参戦の際にはぜひ事前にYAPC行きそうな知り合いを作っておくといいと思います。そう、Chiba.pmとかね(次があるかどうかわからないけど

ポエムでした。

2014/08/30

WHERE狙いのキー、ORDER BY狙いのキー の話を #yapcasia でしてきました

1か月くらい前のエントリー 日々の覚書: YAPC::Asia Tokyo 2014でMySQLのWHERE狙いのキーとORDER BY狙いのキーの話をします の通り、昨日(8/29)のYAPC::Asia 2014 1日目でトークしてきました。

トーク概要 => http://yapcasia.org/2014/talk/show/e495bc1a-f30d-11e3-b7e8-e4a96aeab6a4





字が小さい、背景見にくい、シンタックスハイライトないとつらい、時間余り杉(30分/40分)、その他もろもろツッコミをいただきつつ、次回は改善していきたいと思います。

( ´-`).oO(って、次回は"Groonga How-To Talks"だからあと数日しかないですね。完全にYAPC体制だったのでまだ資料どころか話す内容すらまとまってないですね。


今回の意気込みだった"Kuso-query As A Code"が少しでも伝わったら嬉しいなと思います。エンジニアの共通言語といえばやっぱりコードなので、これからもこういう(MySQLの内部動作をPerlとかなんかで例える)のはやってみたいなーと思います。

しかしトランプの話題をもうちょっとふくらませばよかった。。

足を運んでいただいた皆様、ありがとうございました。

2014/08/25

LOAD DATA LOCAL INFILE .. REPLACE INTO ..の闇

LOAD DATA *LOCAL* INFILEはIGNOREキーワードを指定しなくてもエラーをWarningにフォールバックしてくれる。と思っていた。

With LOAD DATA LOCAL INFILE, data-interpretation and duplicate-key errors become warnings and the operation continues because the server has no way to stop transmission of the file in the middle of the operation. For duplicate-key errors, this is the same as if IGNORE is specified. IGNORE is explained further later in this section.
Treatment of empty or incorrect field values differs from that just described if the SQL mode is set to a restrictive value. For example, if sql_mode='TRADITIONAL, conversion of an empty value or a value such as 'x' for a numeric column results in an error, not conversion to 0. (With LOCAL, warnings occur rather than errors, even with a restrictive sql_mode value, because the server has no way to stop transmission of the file in the middle of the operation.)
http://dev.mysql.com/doc/refman/5.6/en/load-data.html

( ´-`).oO(ER_DUP_ENTRYだけをハンドルするようにも見えれば、ER_WARN_TOO_MANY_RECORDSやER_WARN_TOO_FEW_RECORDSもハンドルしてくれるようにも見える。。

ハンドルの仕方の説明も、ErrorではなくWarningにフォールバックするようにも見えれば、IGNOREと同じように *握りつぶした後にWarningだけ出す* ようにも見える。




そのへんの挙動で毛玉氏がハマっていたようなので、試してみた。


$ echo -e "1\tone" > /tmp/test

mysql56> CREATE TABLE t1 (num int);
Query OK, 0 rows affected (0.07 sec)

カラムの数が合わないテーブルとtsvファイルを用意。


mysql56> SELECT @@sql_mode;
+------------------------+
| @@sql_mode             |
+------------------------+
| NO_ENGINE_SUBSTITUTION |
+------------------------+
1 row in set (0.00 sec)

mysql56> LOAD DATA LOCAL INFILE '/tmp/test' INTO TABLE t1;
Query OK, 1 row affected, 1 warning (0.00 sec)
Records: 1  Deleted: 0  Skipped: 0  Warnings: 1

mysql56> SHOW WARNINGS;
+---------+------+---------------------------------------------------------------------------+
| Level   | Code | Message                                                                   |
+---------+------+---------------------------------------------------------------------------+
| Warning | 1262 | Row 1 was truncated; it contained more data than there were input columns |
+---------+------+---------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql56> TRUNCATE t1;
Query OK, 0 rows affected (0.03 sec)

mysql56> LOAD DATA LOCAL INFILE '/tmp/test' REPLACE INTO TABLE t1;
Query OK, 1 row affected, 1 warning (0.01 sec)
Records: 1  Deleted: 0  Skipped: 0  Warnings: 1

mysql56> SHOW WARNINGS;
+---------+------+---------------------------------------------------------------------------+
| Level   | Code | Message                                                                   |
+---------+------+---------------------------------------------------------------------------+
| Warning | 1262 | Row 1 was truncated; it contained more data than there were input columns |
+---------+------+---------------------------------------------------------------------------+
1 row in set (0.00 sec)

STRICTでないsql_modeな場合、両方ともWarningで出力される。


mysql56> SELECT @@sql_mode;
+---------------------+
| @@sql_mode          |
+---------------------+
| STRICT_TRANS_TABLES |
+---------------------+
1 row in set (0.00 sec)

mysql56> LOAD DATA LOCAL INFILE '/tmp/test' INTO TABLE t1;
Query OK, 1 row affected, 1 warning (0.00 sec)
Records: 1  Deleted: 0  Skipped: 0  Warnings: 1

mysql56> show warnings;
+---------+------+---------------------------------------------------------------------------+
| Level   | Code | Message                                                                   |
+---------+------+---------------------------------------------------------------------------+
| Warning | 1262 | Row 1 was truncated; it contained more data than there were input columns |
+---------+------+---------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql56> LOAD DATA LOCAL INFILE '/tmp/test' REPLACE INTO TABLE t1;
ERROR 1262 (01000): Row 1 was truncated; it contained more data than there were input columns

STRICTなsql_modeでLOAD DATA LOCAL INFILE .. *REPLACE* INTO .. の場合は、エラーになってアボートする。

ざっと読んだ感じ、LOAD DATA LOCAL INFILEの時はエラー(やワーニング)を握りつぶしてから *最後に* その内容をWarningとして出力するのに対し、LOAD DATA LOCAL INFILE .. REPLACE INTO ..のときは最初からWarningとして扱っているので、STRICT_TRANS_TABLESに引っかかってエラーに昇格されている。


318   /* We can't give an error in the middle when using LOCAL files */
 319   if (read_file_from_client && handle_duplicates == DUP_ERROR)
 320     ignore= 1;

REPLACEなしのLOAD DATA LOCAL INFILEの時はここでignore= 1(エラーやワーニングを握りつぶしてから *最後に* その内容をWarningとして出力)をセットする。


Breakpoint 1, mysql_load (thd=0x36c9430, ex=0x7f217c373170, table_list=0x7f217c373200, fields_vars=..., set_fields=...,
    set_values=..., handle_duplicates=DUP_ERROR, ignore=false, read_file_from_client=true)
    at /home/yoku0825/mysql-5.6.20/sql/sql_load.cc:190
190     {
(gdb) p thd->query_string->string->str
$3 = 0x7f217c373080 "LOAD DATA LOCAL INFILE '/tmp/test' INTO TABLE t1"

Breakpoint 1, mysql_load (thd=0x36c9430, ex=0x7f217c373180, table_list=0x7f217c373210, fields_vars=..., set_fields=...,
    set_values=..., handle_duplicates=DUP_REPLACE, ignore=false, read_file_from_client=true)
    at /home/yoku0825/mysql-5.6.20/sql/sql_load.cc:190
190     {
(gdb) p thd->query_string->string->str
$2 = 0x7f217c373080 "LOAD DATA LOCAL INFILE '/tmp/test' REPLACE INTO TABLE t1"

REPLACEありの場合、handle_duplicates= DUP_REPLACEでこの箇所が呼ばれるため、ignore= 1にならない。

これがドキュメント上のバグ(REPLACEキーワードを指定した場合はエラーハンドルの仕方が更に変わる)なのか、REPLACEキーワードがあった時のエラーハンドルの不備なのか(sql/sql_load.cc:319 の条件文が (read_file_from_client && (handle_duplicates == DUP_ERROR || handle_duplicates == DUP_REPLACE)) でなければならないのか)は知らない。

とりあえずドキュメント上のバグとしてレポートはした。。

http://bugs.mysql.com/bug.php?id=73654

2014/08/07

Percona ServerでMroongaの./configureに失敗したら

Percona Server 5.6.19にMroonga(故あってGroonga 3.1.0のnightly + Mroonga 3.10だけど)を載せようとしたら、configureスクリプトが転けた。


$ ./configure CFLAGS=-O3 CXXFLAGS=-O3 PKG_CONFIG_PATH=/usr/groonga/3.1.0.20131209/lib/pkgconfig --with-mysql-source=/usr/local/src/percona-server-5.6.19-67.0 --with-mysql-config=/usr/local/percona5619/bin/mysql_config
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
..
checking mysql source... yes
checking mysql_config... /usr/local/percona5619/bin/mysql_config
checking for libmysqlservices.a directory... configure: error: libmysqlservices.a is not found in </usr/local/percona5619/lib/mysql/> and </usr/local/percona5619/lib/mysql/mysql/>

libmysqlservices.aが見つからないんだって。


$ ll /usr/local/percona5619/lib/libmysqlservices.a
-rw-r--r-- 1 root root 15662  7月  1 18:20 /usr/local/percona5619/lib/libmysqlservices.a

あるんだけどなぁ…ん? 俺なんかこれ知ってる気がしてきた。
ああ、これかな。。

日々の覚書: Percona Serverのmysql_configが変?

Bug #1099681 “mysql_config returns wrong path” : Bugs : Percona Server


$ /usr/local/percona5619/bin/mysql_config --variable=pkglibdir
/usr/local/percona5619/lib/mysql

$ ll /usr/local/percona5619/lib/mysql
合計 1372
lrwxrwxrwx 1 root root      16  8月  7 12:10 libjemalloc.so -> libjemalloc.so.1
-rwxr-xr-x 1 root root 1395722  7月  1 18:26 libjemalloc.so.1
drwxr-xr-x 2 root root    4096  8月  7 16:32 plugin

OK大正解。
Mroongaのconfigureスクリプトはlibmysqlservices.aのありかをmysql_config --variable=pkglibdirから探すから…ってこれ、こんなことをだいぶ前にgroonga-devでも言ったような気がする。

Feature #1730: [groonga-dev,01335] mysql 5.6.11でmroonga 3.03をビルドするとエラー - Mroonga - Groonga issues!


…なるほどなるほど。
というわけでconfigureスクリプトをほげって何とかした。


$ diff -c configure.orig configure
diff -c configure.orig configure
*** configure.orig      Thu Aug  7 17:18:35 2014
--- configure   Thu Aug  7 17:18:45 2014
***************
*** 18363,18369 ****
      *)
          { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libmysqlservices.a directory" >&5
  $as_echo_n "checking for libmysqlservices.a directory... " >&6; }
!         pkglibdir="$($ac_mysql_config --variable=pkglibdir)"
          mysql_build_libservices_dir="${MYSQL_BUILD_DIR}/libservices"
          if test -f "${mysql_build_libservices_dir}/libmysqlservices.a"; then
            mysql_services_lib_dir="${mysql_build_libservices_dir}"
--- 18363,18369 ----
      *)
          { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libmysqlservices.a directory" >&5
  $as_echo_n "checking for libmysqlservices.a directory... " >&6; }
!         pkglibdir="/usr/local/percona5619/lib"
          mysql_build_libservices_dir="${MYSQL_BUILD_DIR}/libservices"
          if test -f "${mysql_build_libservices_dir}/libmysqlservices.a"; then
            mysql_services_lib_dir="${mysql_build_libservices_dir}"

早く直らないかなこれってか忘れられてんじゃないかな。。