不動の鳥の勉強記録

時間があるときに勉強したことをメモします。

Node.jsでMySQL 8.0へ接続する

2019年一つ目の記事は、Node.jsでMySQLのDBへ接続するプログラムについてです。
いろいろな方がすでに記事を投稿されていますが、学んだことはアウトプットするのが今年の目標なので、
いつか見返す時のために記事にして残しておきます。
新年なので、環境系のフレームワークはとりあえず全部最新にしていきたいと思います。
何か問題があったらバージョン落とします。

■環境

 OS: Windows 10 Home 64bit
 DB: MySQL Server 8.0 Community Edition
 node: v10.15.0
 npm: 6.4.1
 mysql: 2.16.0
 

■アウトライン

 1. DBにテーブルを作成する
 2. MySQLに接続するためのドライバをインストールする
 3. DBに接続しSELECTするスクリプトを作成する

早速まとめていきたいと思います。

1. DBにテーブルを作成する。

簡単なテーブルを一つMySQLに作成します。
このテーブルにデータを入れたり、選択したりしていきます。

-- スキーマを作成する。
CREATE DATABASE `nodesample` DEFAULT CHARACTER SET utf8 ;

-- スキーマ内にテーブルを作成する。
USE nodesample;

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) NOT NULL,
  `age` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- サンプルに1件レコードを挿入する。
INSERT user(name, age) VALUES ('太郎', '30');
2. MySQLに接続するためのドライバをインストールする

MySQLへの接続のモジュール(ドライバ)としてmysqlが有名とのことで早速インストールします。
www.npmjs.com

コマンドプロンプトを開いて次のコマンドを実行します。

npm install mysql

しばらくたつとインストールが完了します。
package-lock.jsonをみると今回インストールしたmysqlは、2.16.0でした。

3. DBに接続しSELECTするスクリプトを作成する

mysqlのページを参考にとりあえずDBに接続するスクリプトを作成します。

/* sample.js */
'use strict'

const mysql = require('mysql');
const connection = mysql.createConnection({
    host: '127.0.0.1',
    user: 'nodeuser',
    password: 'nodeuser',
    database: 'nodesample',
});

// Connectionを定義する
connection.connect();

let sql = 'select * from nodesample.user';
connection.query(sql, (err, rows, fields) => {
    if (err) throw err;
    console.log('userテーブル: ', rows);
});

connection.end();

で次のコマンドで試してみるとエラーが発生しました。

node sample.js
D:\workspace\MySQL-Sample\sample\sample.js:17
    if (err) throw err;
             ^

Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client
    at Handshake.Sequence._packetToError (D:\workspace\MySQL-Sample\sample\node_modules\mysql\lib\protocol\sequences\Sequence.js:47:14)
    at Handshake.ErrorPacket (D:\workspace\MySQL-Sample\sample\node_modules\mysql\lib\protocol\sequences\Handshake.js:124:18)
    at Protocol._parsePacket (D:\workspace\MySQL-Sample\sample\node_modules\mysql\lib\protocol\Protocol.js:278:23)
    at Parser.write (D:\workspace\MySQL-Sample\sample\node_modules\mysql\lib\protocol\Parser.js:76:12)
    at Protocol.write (D:\workspace\MySQL-Sample\sample\node_modules\mysql\lib\protocol\Protocol.js:38:16)
    at Socket.<anonymous> (D:\workspace\MySQL-Sample\sample\node_modules\mysql\lib\Connection.js:91:28)
    at Socket.<anonymous> (D:\workspace\MySQL-Sample\sample\node_modules\mysql\lib\Connection.js:502:10)
    at Socket.emit (events.js:182:13)
    at addChunk (_stream_readable.js:283:12)
    at readableAddChunk (_stream_readable.js:264:11)
    --------------------
    at Protocol._enqueue (D:\workspace\MySQL-Sample\sample\node_modules\mysql\lib\protocol\Protocol.js:144:48)
    at Protocol.handshake (D:\workspace\MySQL-Sample\sample\node_modules\mysql\lib\protocol\Protocol.js:51:23)
    at Connection.connect (D:\workspace\MySQL-Sample\sample\node_modules\mysql\lib\Connection.js:118:18)
    at Object.<anonymous> (D:\workspace\MySQL-Sample\sample\sample.js:13:12)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)

■エラーメッセージ

Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server;

でグーグルを検索すると、Node.jsでMySQL 8.0へ接続しようとするときにみなさん発生しているようです。
一番参考になったのが下記ページの次のコメントでログイン時のパスワード認証が変更になっているのが、
mysqlで対応していないそうです。
node.js - MySQL 8.0 - Client does not support authentication protocol requested by server; consider upgrading MySQL client - Stack Overflow

This is because caching_sha2_password is introduced in MySQL 8.0, but the Node.js version is not implemented yet. You can see this pull request and this issue for more information. Probably a fix will come soon!

そのため、ログインユーザのパスワードをMySQL Wrokbenchから変更します。
※アカウント名とパスワードが同一なのはサンプルのためなので、普段は絶対にしないようにしましょう。

ALTER USER 'nodeuser'@'localhost' IDENTIFIED WITH mysql_native_password BY 'nodeuser';
FLUSH PRIVILEGES;

これで再度サンプルスクリプトを実行してみるとレコードを選択することができました。

node sample.js
userテーブル:  [ RowDataPacket { id: 1, name: '太郎', age: 30 } ]

■終わりに

今回RDBMSMySQLを選択したのは、将来的にAWS Auroraへの移植を考えてSQL Server以外の製品を選択してみました。
SQL ServerはEnterprise版は2コアでいいお値段するので、SQL Serverを選択する理由はあまりなくなってきてしまいました。ただ、プレミアサポートなどのサポート体制があるのは強味ですね。

以上。