カテゴリー
MySQL データベース

いろんな言語でMySQLに接続してみよう

フリーランスプログラマーの増子です。

今までPerlを中心にお仕事をしてきて、Perlは嫌いだとか思ったことはないのだけれども、
色々な言語を知っていた方がこの先に役に立つのかなということもあったり、
お仕事で使うかもしれないので色々と勉強しているコードを公開しちゃいます。

まずは基本的なhello world。。。だとつまらないので、
いろんなプロジェクトでよく使われているMySQLに接続してしまいましょう。

データベースの作り方はここでは省略します。

  • データベース名:db
  • 接続テーブル名:author
  • 接続ユーザ名:user
  • 接続パスワード:password

※あくまでローカルの開発環境で説明しやすいように作りました。本番環境でこんなパスワードとか使っちゃダメ絶対!!

プログラムの内容は、authorテーブルに接続し、idとnameを表示するだけの簡単なお仕事。
言語ごとにどんな違いがあるのでしょうか。
楽しみですね。

さて、始めていきましょう!

Pythonの場合

PythonはPerlなんかと同じ動的言語と呼ばれるもので、コンパイルなどの作業をプログラマがやらずとも動いてくれる言語です。
楽チンですね。
インデントでプログラムの塊(関数の切れ目とかif文はどこまでだとか)を判断してくれるので、文章の終わりにセミコロン等は必要ありません。
どうしても1行に2つの命令を入れたい場合にはセミコロンで区切ることもできますが、読みにくくなるしやらない。

PythonからMySQLに接続するのみよく使われているのがMySQL-pythonというモジュールみたいです。
他にも色々あったり、Pythonのバージョンが2か3かで違ったりするので、自分がどのバージョンで使おうとしているのか事前に調べておきましょう。

今回はPython3系で説明します。

早速ソースコードを載せちゃいます。

# -*- coding: utf-8 -*- 

import MySQLdb
  
if __name__ == "__main__":
  
    connector = MySQLdb.connect(host="192.168.33.50", db="db", user="user", passwd="password", charset="utf8")
    cursor = connector.cursor(MySQLdb.cursors.DictCursor)
      
    sql = "select * from author"
    cursor.execute(sql)
    records = cursor.fetchall()
    for record in records:
        print "id = " + str(record["id"]) + ", author_name= " + str(record["name"])
    cursor.close()
    connector.close()

見やすいように改行とか入れてますが、スマホとかだとちょっと見辛いかもしれません。

7行目:MySQLdb.connect()というところでdbに接続します。
8行目:カーソルを取得します。この時に、ハッシュでデータをもらいたいのでそのあたりもやってます。
11行目:sqlという変数に入っているSQL文を実行します。
12行目:fetchall()というところですべてのデータを配列で受け取ります。
14行目:受け取った配列をfor文で順番に取得して、printしています。
15、16行目:コネクションを閉じたり終わりの処理

15、16行目はwithとかで書くと入らなくなるらしいというかプログラムの実行が終わると自動的にコネクション閉じてくれそうなものだけど、最初なので丁寧に閉じるところまでやってみた。

つまずいたのは14行目で文字列を連結させてprintしていますが、idがintegerのため、『str()』で文字列に変換しています。
これをやらないと、書きエラーが発生します。

TypeError: cannot concatenate ‘str’ and ‘long’ objects

最近はMovableTypeもそうだし、他のフレームワークでも生のSQLを書くことがないので久しぶりに書きました。
ただのselect文なのに緊張するw

データベースへの接続ってもっとかかるかと思ったけど以外と簡単に行けた。

次行ってみよー

Rubyの場合

みんな大好きRuby on RailsのRubyです。

言語を作ったのは日本人(まつもと ひろゆき さん)が作ったので日本語の情報もいっぱいあっていいですね!
Perlは結構英語のサイトを読むことに。。。

RubyもPythonやPerlと同じくコンパイル作業が必要ない動的言語です。
そしてRubyもPythonと同じく文章の終わりにセミコロンなどが必要なしです。
if文などの塊はif〜endまでと日本人的にはわかりやすい形になってます。
少なくとも{{{}}}}あれ?カッコ一個多くない?みたいなことにはなりませんね。

RubyからMySQLに接続する場合には、mysql2というライブラリが最近は人気だとか。
流行りには乗っかるタイプなのでこちらでやってみたいと思います。

今回Railsはあえて使用しませんでした。
言語として比較したかったので、素のRubyです。

では早速ソースコード書いて見ましょう。

require 'mysql2'

client = Mysql2::Client.new(:host => '192.168.33.50', :user => 'user', :password => 'password', :encoding => 'utf8', :database => 'db')
query = %q{select * from author}
results = client.query(query)
results.each do |row|
  puts "id = " + row["id"].to_s + ", name= " + row["name"].to_s
end

こちらもPythonとほぼ同じですね。
なるべく言語間で比較ができるように同じになるように書いているので当然といえば当然か。

Pythonよりスッキリしているのはカーソル周りの処理がないから。
ちょこっと調べた限りだとどこもこんな感じなので、どうなんでしょう?

細かいところだと、こちらもidをprintするときに文字列連結しているので『to_s』というメソッドを呼び出して文字列に変換しています。
これをやらないと、Pythonと同じようにエラーが発生します。

no implicit conversion of Fixnum into String (TypeError)

とりあえずRubyでも接続成功!

 

カテゴリー
movabletype(mt) MySQL Perl データベース

MySQL server has gone away エラー対処方法

ある日突然エラーログにて

「MySQL server has gone away」という表示が出てきました。

直訳すると、MySQLサーバが立ち去りました。

おーい!勝手にどっかに立ち去らないでいただけますか〜!?

それにしても面白いメッセージ。考えた人センスあるね。

このエラーが出た時の状況としては、画像をbase64にしてHTML内に入れているソースをMovableTypeの記事のHTMLにぶっ込んで、

ローカル環境で保存したところ、ログにエラーが表示されました。

Perl的にも困るよね。勝手にどっか行かれたら。

大きなデータを任せた結果、逃げてったのかな。

さて、どこに行ったのかな?とエラーメッセージで調べると、ありました。

MySQL サーバーが存在しなくなりました

こっちは存在しなくなりましたって書いてある。対処法は「max_allowed_packet」を大きめにしようというものでした。

初期値は、、、1M。画像のデータとか入っているから2Mは超えている。16Mが最大らしいので、とりあえず最大に設定して再起動!

MovableTypeに戻って保存。うまくいきました。

エラーメッセージってもう少しなんとかならないもんかなぁ。

増子良太は立ち去りました!

カテゴリー
MySQL データベース

mysqlの設定は奥が深い

最近mysqlの設定を変えてはMTの再構築を繰り返しているrmascoです

mysqlのロゴです

mysqlの設定は基本的にmy.cnfで行います。

my.cnfの中には様々な設定値がかけて、それぞれが色々な意味を持っています。

ここで全てを紹介できないので、innoDBを使っている場合に重要な項目だけ記録として書いておきます。

 

innodb_file_format

データ圧縮機能を使う際のフォーマットを指定するらしい。innoDBはMyIsamよりファイルサイズが大きくなるらしい。
そこでこうした設定を有効にすることで、圧縮して小さくする。

ということですが、フォーマットの違いで何が起こるのかはよくわかりません。
次に登場するinnodb_file_per_tableと一緒に使うらしいです

innodb_file_per_table

innodb_file_per_tableはデータファイルをテーブル毎に分けるかどうかの設定らしい。

通常は「ibdata1」というファイルがデータが増えるとどんどん大きくなっていくけど、
この設定を有効にすることで、テーブル毎にデータファイルを作成するから、
データが大きくなってもテーブルを消せば、領域を確保できたりするらしいです。

ただ、どちらにしてもibdata1というファイルは大きいけれども。

innodb_additional_mem_pool_size

innodb_additional_mem_pool_sizeはテーブルの情報なんかをキャッシュしておくサイズを指定するみたいです。

色んなサイトにエラーが出たら少し大きくしてやれば良いみたいなことが書いてある。
適当でよいと。

innodb_buffer_pool_size

innodb_buffer_pool_sizeはinnoDBでパフォーマンスを上げたいときには重要な項目の一つだそうです。
データやインデックスなどをキャッシュしておくサイズで、このサイズ内であればディスクの書き込みが発生しないので、
高速ってわけですね。

実メモリの80%くらいの大きさに指定すると良いらしです。

innodb_log_file_size

innodb_log_file_sizeはコミットされたものを一時的にメモリに貯めておくことでデータベースへ高速に書き込みをするためのサイズみたい。

32bitの環境の場合は4Gまでの制約があるのと、innodb_log_file_size × innodb_log_files_in_groupがinnodb_buffer_pool_size以下になるようにしないといけないらしい。

innodb_log_buffer_size

innodb_log_buffer_sizeはデータ更新時のログをメモリ上においておくためのサイズを指定するらしい。

でも8M以上にしても意味がないとのこと

MT5.27でPSGI、mysql5.5でinnoDBを使うと、fastCGIでMyIsamと比べるとだいぶ早くなる。
もちろんfastCGIの環境でもちゃんと設定をしたりすることで早くなるんでしょうが、
PSGIのほうはあまり設定とかしなくても早い(設定するともっと早い)

ただ、mysqlの設定、bufferだのlogだのメモリに関する設定が多くて、イマイチ理解しきれておりませんが。。。
ちゃんとメモリを使い果たすような設定にすれば、最高のパフォーマンスが得られるよってことか。

もちろんアプリ側でもパフォーマンス・チューニングはすべきですが!