【RDB】Node.js から MySQL を使ってみる

前に カラム指向DB の Cassandra について書いたので, 今回はRDBの MySQLとの連携について書きます。
Node.jsから MySQL に接続する node-mysqlを試します。

サーバの準備

Red-hat系では yum を使って mysql-serverをインストールします。

$ sudo yum install mysql-server

Node.js (v0.10.12)をnodejs.orgから入手します。
Node.jsのパッケージ管理ツールの nvmをインストールします。

$ git clone git://github.com/creationix/nvm.git ~/.nvm
$ nvm use  v0.10.12
Now using node v0.10.12
$ npm install express

node-mysqlをインストールします。

$ npm install mysql -g

./bash_profile も編集しときます。

export NODE_PATH="/usr/local/lib/node"

RDBとSQL

RDBとSQLの初心者が数日間, 勉強した内容のメモ。

RDB (relational database)に関する理論は, 数学の集合論を背景としています。

RDBはおおよそ下記で構成されます。各要素の詳細は専門的に解説しているサイトを見てください。

  • クエリ評価エンジン
  • バッファマネージャ
  • ディスク容量マネージャ
  • トランザクションマネージャ
  • リカバリマネージャ

RDBはデータを Relation (具体的な実装としては Table)という形式で保存しています。
RDB製品は商用だとOracle, Microsoft SQL Server, OSSだとMySQL, PostgreSQLが有名です。

SQLはRDBを操作するための言語です。大きく3種類に分類されることが多いです。

  • DDL(Data Definition Language) : データ定義言語
  • DML(Data Manipulation Language) : データ操作言語
  • DCL(DataControl Language) : データ制御言語

SQLは集合指向 (Set Oriented)な言語で, 手続き型言語の考えも一部取り入れていますが基本的には宣言的に書いていくことが大切です。
例えばSQLは言語的にループを排除しており, 関数型言語にも通じる側面があると思います。

MySQLの基礎

MySQLはRDBのOSS実装のひとつです。SQL文は大文字で書きますが, 小文字でも解釈されるので小文字にしています。

まずはユーザ指定でログインしてTableを作り, Recordを挿入してみます。

$ mysql -u [user] -p
$ use [database];
$ create table [table_name] ([key] [dataType]);
$ insert into [table_name] ([ley]) values([value]);

Tableの中身を表示します。 全ての列を表示する場合は, * を使います。whereで条件指定をします。
asで alias (別名)をつけることができます。

$ select * from [table] where [column] = 'key';

Tableのデータを更新します。select同様, whereで条件指定ができます。

$ update [table] set [column] = [value] where [column] = 'key';

NULLに対して, 算術演算子 (+,-,*,/,%) は使えません。
これは算術演算子は値に対して使える演算ですが, NULL はデータの値ではないためです。
判定には is / is not を使います。

$ select * from [table]  where [column_1] is NULL and [column_2] = 'key';

delete は Table の Record を削除します。

$ delete * from [table]  where [column] = 'key';

Table自体の削除は drop を使います。

$ drop table [table];

SQLは他にも下記のような多様な構文/機能を持っています。これらの中の幾つかは, そのうち深堀りして詳しく書きたいなと思います。

  • 集合演算子 (UNION, INTERSECTIONなど)
  • 論理演算子 (AND, ORなど)
  • LIKE演算子 (LIKE)
  • CASE式
  • VIEW
  • 結合 (INNER JOIN, OUTERなど)
  • グループ化と集計関数 (GROUP BY, HAVIMGなど)
  • 述語 (IN, ALL, EXISTS)
  • サブクエリ / 相関サブクエリ
  • トランザクション制御

文字コードを utf-8に変更したい時は MySQLの設定ファイル /etc/my.cnf を編集します。

datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mysqld according to the
# instructions in https://fedoraproject.org/wiki/Systemd

# add 2-line
skip-character-set-client-handshake
character-set-server=utf8

mysqlデーモンを再起動します。動いてるかは service mysqld statusで確認します。

$ sudo service mysqld restart

node-mysqlをつかってみる

nodejs から mysql に接続します。

require('mysql')
...

var connection = mysql.createConnection({
  host     : 'localhost', //接続先ホスト
  user     : 'xxx',      //ユーザー名
  password : 'xxx',  //パスワード
  database : 'test'    //DB名
});
connection.connect();

app.post(‘/set.json’, function(req, res){…} みたいなハンドラを書いて mysqlに接続しクエリを発行します。コードは適当です。

var ReqData = new Object;// JSONデータをobjectに格納

...
var insertData = "insert into catcode  (_id,web_level,clang_level,objc_level,special_level) values ('" + ReqData._id + "'," + ReqData.web_level + "," + ReqData.clang_level + "," + ReqData.objc_level + "," + ReqData.special_level + ");"
console.log("new-create-row : " + insertData);
var query = connection.query(insertData);// クエリ発行
query
  .on('error', function(err) {console.log('err is: ', err );})
  .on('result', function(rows) {console.log('The res is: ', rows );})
  .on('end_insert', function() {connection.destroy()}) //終了

実際にクライアントからHTTPでデータを postし、サーバ側で確認します。

mysql> use test
Database changed
mysql> select * from catcode;
+----------------+-----------+-------------+------------+---------------+
| _id            | web_level | clang_level | objc_level | special_level |
+----------------+-----------+-------------+------------+---------------+
| 20130707083831 |         0 |           1 |          2 |             0 |
+----------------+-----------+-------------+------------+---------------+

その他

その他, 何点かTIPSを残しておきます。memcachedのダンプは以下の書式です。

$ memcached-tool [IP]:[port] dump

MySQLでデータをCSVで出力したいときのクエリ。

select * from **** into outfile "/tmp/dump.csv" fields terminated by ',';

mysqlをデーモンで起動したいとき。

$ /etc/init.d/mysqld start

foeverで Nodeアプリケーション をデーモン化。

$ npm install forever -g
$ forever start app.js

“MySQL Daemon failed to start.” とエラーを吐いたらまず my.cnf を確認しましょう。
MySQLにログインして, 設定変更が適用されているか確認します。

 $ show variables like 'char%';
# statusでも見れる
$ create table xxx (xxx)  default character set utf8;

札幌の海鮮丼は美味しかった。全体的に東京より飯が安くて美味しい印象。