原博文出自于:  http://blog.fens.me/category/%E6%95%B0%E6%8D%AE%E5%BA%93/page/2/      感谢!

用Nodejs连接MySQL

从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发。Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎。chrome浏览器就基于V8,同时打开20-30个网页都很流畅。Nodejs标准的web开发框架Express,可以帮助我们迅速建立web站点,比起PHP的开发效率更高,而且学习曲线更低。非常适合小型网站,个性化网站,我们自己的Geek网站!!

关于作者

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/nodejs-mysql-intro/

前言

MySQL是一款常用的开源数据库产品,通常也是免费数据库的首选。查了一下NPM列表,发现Nodejs有13库可以访问MySQL,felixge/node-mysql似乎是最受关注项目,我也决定尝试用一下。

要注意名字,”felixge/node-mysql”非”node-mysql”,安装部分会介绍这个小插曲!

目录

  1. node-mysql介绍
  2. 建立MySQL测试库
  3. node-mysql安装
  4. node-mysql使用

1. node-mysql介绍

felixge/node-mysql是一个纯nodejs的用javascript实现的一个MySQL客户端程序。felixge/node-mysql封装了Nodejs对MySQL的基本操作,100% MIT公共许可证。

项目地址:https://github.com/felixge/node-mysql

2. 建立MySQL测试库

本地创建MySQL测试库:nodejs


~ mysql -uroot -p
mysql> CREATE DATABASE nodejs;
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| nodejs |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec) mysql> GRANT ALL ON nodejs.* to nodejs@'%' IDENTIFIED BY 'nodejs';
mysql> GRANT ALL ON nodejs.* to nodejs@localhost IDENTIFIED BY 'nodejs';

重新登陆MySQL


C:\Users\Administrator>mysql -unodejs -p
Enter password: ****** mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| nodejs |
| test |
+--------------------+
3 rows in set (0.00 sec) mysql> USE nodejs
Database changed

新建一个user表


CREATE TABLE t_user(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(16) NOT NULL ,
create_date TIMESTAMP NULL DEFAULT now()
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE UNIQUE INDEX t_quiz_IDX_0 on t_user(name); mysql> SHOW TABLES;
+------------------+
| Tables_in_nodejs |
+------------------+
| t_user |
+------------------+
1 row in set (0.04 sec)

3. node-mysql安装

我的系统环境

  • win7 64bit
  • Nodejs:v0.10.5
  • Npm:1.2.19
  • MySQL:Server version: 5.6.11 MySQL Community Server (GPL)

创建工程:nodejs-node-mysql

~ D:\workspace\javascript>mkdir nodejs-node-mysql
~ D:\workspace\javascript>cd nodejs-node-mysql
~ D:\workspace\javascript\nodejs-node-mysql>npm install node-mysql
node-mysql@0.2.0 node_modules\node-mysql
├── better-js-class@0.1.2
├── cps@0.1.7
├── underscore@1.5.2
└── mysql@2.0.0-alpha9 (require-all@0.0.3, bignumber.js@1.0.1)

这里有一个小插曲

安装“node-mysql”后,打开package.json文件发现,这个项目地址是

https://github.com/redblaze/node-mysql.git

从依赖关系可以看到,它依赖于mysql库,是对felixge/node-mysql的封装。

由于这个项目star是0,fork也是0. 所以,我也不准备花时间测试了,重新安装felixge/node-mysql的包。

重新安装node-mysql

~ D:\workspace\javascript\nodejs-node-mysql>rm -rf node_modules
~ D:\workspace\javascript\nodejs-node-mysql>npm install mysql@2.0.0-alpha9
npm http GET https://registry.npmjs.org/mysql/2.0.0-alpha9
npm http 200 https://registry.npmjs.org/mysql/2.0.0-alpha9
npm http GET https://registry.npmjs.org/mysql/-/mysql-2.0.0-alpha9.tgz
npm http 200 https://registry.npmjs.org/mysql/-/mysql-2.0.0-alpha9.tgz
npm http GET https://registry.npmjs.org/require-all/0.0.3
npm http GET https://registry.npmjs.org/bignumber.js/1.0.1
npm http 304 https://registry.npmjs.org/require-all/0.0.3
npm http 304 https://registry.npmjs.org/bignumber.js/1.0.1
mysql@2.0.0-alpha9 node_modules\mysql
├── require-all@0.0.3
└── bignumber.js@1.0.1

这回就对了,继续下面的开发!

创建node程序启动文件:app.js

第一个测试

~ vi app.js

var mysql = require('mysql');
var conn = mysql.createConnection({
host: 'localhost',
user: 'nodejs',
password: 'nodejs',
database:'nodejs',
port: 3306
});
conn.connect();
conn.query('SELECT 1 + 1 AS solution', function(err, rows, fields) {
if (err) throw err;
console.log('The solution is: ', rows[0].solution);
});
conn.end();

运行node

~ D:\workspace\javascript\nodejs-node-mysql>node app.js
The solution is: 2

这样我们就让Nodejs连接上了MySQL。

4. node-mysql使用

下面我们要对node-mysql的API进行常用的测试。

  • 表新删改查
  • 连接池配置
  • MySQL断线重连
  • 连接池超时测试

1). 表新删改查
修改app.js


~ vi app.js var mysql = require('mysql');
var conn = mysql.createConnection({
host: 'localhost',
user: 'nodejs',
password: 'nodejs',
database: 'nodejs',
port: 3306
});
conn.connect(); var insertSQL = 'insert into t_user(name) values("conan"),("fens.me")';
var selectSQL = 'select * from t_user limit 10';
var deleteSQL = 'delete from t_user';
var updateSQL = 'update t_user set name="conan update" where name="conan"'; //delete
conn.query(deleteSQL, function (err0, res0) {
if (err0) console.log(err0);
console.log("DELETE Return ==> ");
console.log(res0); //insert
conn.query(insertSQL, function (err1, res1) {
if (err1) console.log(err1);
console.log("INSERT Return ==> ");
console.log(res1); //query
conn.query(selectSQL, function (err2, rows) {
if (err2) console.log(err2); console.log("SELECT ==> ");
for (var i in rows) {
console.log(rows[i]);
} //update
conn.query(updateSQL, function (err3, res3) {
if (err3) console.log(err3);
console.log("UPDATE Return ==> ");
console.log(res3); //query
conn.query(selectSQL, function (err4, rows2) {
if (err4) console.log(err4); console.log("SELECT ==> ");
for (var i in rows2) {
console.log(rows2[i]);
}
});
});
});
});
}); //conn.end();

控制台输出:

D:\workspace\javascript\nodejs-node-mysql>node app.js
DELETE Return ==>
{ fieldCount: 0,
affectedRows: 2,
insertId: 0,
serverStatus: 34,
warningCount: 0,
message: '',
protocol41: true,
changedRows: 0 }
INSERT Return ==>
{ fieldCount: 0,
affectedRows: 2,
insertId: 33,
serverStatus: 2,
warningCount: 0,
message: '&Records: 2 Duplicates: 0 Warnings: 0',
protocol41: true,
changedRows: 0 }
SELECT ==>
{ id: 33,
name: 'conan',
create_date: Wed Sep 11 2013 12:09:15 GMT+0800 (中国标准时间) }
{ id: 34,
name: 'fens.me',
create_date: Wed Sep 11 2013 12:09:15 GMT+0800 (中国标准时间) }
UPDATE Return ==>
{ fieldCount: 0,
affectedRows: 1,
insertId: 0,
serverStatus: 2,
warningCount: 0,
message: '(Rows matched: 1 Changed: 1 Warnings: 0',
protocol41: true,
changedRows: 1 }
SELECT ==>
{ id: 33,
name: 'conan update',
create_date: Wed Sep 11 2013 12:09:15 GMT+0800 (中国标准时间) }
{ id: 34,
name: 'fens.me',
create_date: Wed Sep 11 2013 12:09:15 GMT+0800 (中国标准时间) }

由于node的异步的,上面是一个连续的操作,代码会被写的支离破碎。我们可以通过async库对上面代码进行封装,请参考文章:Nodejs异步流程控制Async

2). 连接池配置

增加文件:app-pooling.js

~ vi app-pooling.js

var mysql = require('mysql');
var pool = mysql.createPool({
host: 'localhost',
user: 'nodejs',
password: 'nodejs',
database: 'nodejs',
port: 3306
}); var selectSQL = 'select * from t_user limit 10'; pool.getConnection(function (err, conn) {
if (err) console.log("POOL ==> " + err); conn.query(selectSQL,function(err,rows){
if (err) console.log(err);
console.log("SELECT ==> ");
for (var i in rows) {
console.log(rows[i]);
}
conn.release();
});
});

控制台输出:

D:\workspace\javascript\nodejs-node-mysql>node app-pooling.js
SELECT ==>
{ id: 39,
name: 'conan update',
create_date: Wed Sep 11 2013 13:41:18 GMT+0800 (中国标准时间) }
{ id: 40,
name: 'fens.me',
create_date: Wed Sep 11 2013 13:41:18 GMT+0800 (中国标准时间) }

3). MySQL断线重连

分别模拟3种错误

  • 登陆密码错误
  • 数据库宕机
  • 数据库连接超时

新增文件:app-reconnect.js

~ vi app-reconnect.js

var mysql = require('mysql');
var conn;
function handleError () {
conn = mysql.createConnection({
host: 'localhost',
user: 'nodejs',
password: 'nodejs',
database: 'nodejs',
port: 3306
}); //连接错误,2秒重试
conn.connect(function (err) {
if (err) {
console.log('error when connecting to db:', err);
setTimeout(handleError , 2000);
}
}); conn.on('error', function (err) {
console.log('db error', err);
// 如果是连接断开,自动重新连接
if (err.code === 'PROTOCOL_CONNECTION_LOST') {
handleError();
} else {
throw err;
}
});
}
handleError();

a. 模拟密码错误

修改password: ‘nodejs11’

控制台输出。

D:\workspace\javascript\nodejs-node-mysql>node app-reconnect.js
error when connecting to db: { [Error: ER_ACCESS_DENIED_ERROR: Access denied for user 'nodejs'@'localhost' (using pass
rd: YES)]
code: 'ER_ACCESS_DENIED_ERROR',
errno: 1045,
sqlState: '28000',
fatal: true }
error when connecting to db: { [Error: ER_ACCESS_DENIED_ERROR: Access denied for user 'nodejs'@'localhost' (using pass
rd: YES)]
code: 'ER_ACCESS_DENIED_ERROR',
errno: 1045,
sqlState: '28000',
fatal: true }

b. 模拟数据库宕机
正常启动node,然后杀掉mysqld的进程。

控制台输出。


D:\workspace\javascript\nodejs-node-mysql>node app-reconnect.js
db error { [Error: read ECONNRESET]
code: 'ECONNRESET',
errno: 'ECONNRESET',
syscall: 'read',
fatal: true } Error: read ECONNRESET
at errnoException (net.js:884:11)
at TCP.onread (net.js:539:19)

这个异常,直接导致node程序被杀死!

c. 模拟连接超时,PROTOCOL_CONNECTION_LOST
切换到root账户, 修改MySQL的wait_timeout参数,设置为10毫秒超时。

~ mysql -uroot -p
mysql> show variables like 'wait_timeout';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout | 28800 |
+---------------+-------+
1 row in set (0.00 sec) mysql> set global wait_timeout=10;
Query OK, 0 rows affected (0.00 sec) mysql> show variables like 'wait_timeout';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout | 10 |
+---------------+-------+
1 row in set (0.00 sec)

修改文件:app-reconnection.js,在最后增加代码

~ vi app-reconnection.js

function query(){
console.log(new Date());
var sql = "show variables like 'wait_timeout'";
conn.query(sql, function (err, res) {
console.log(res);
});
} query();
setInterval(query, 15*1000);

程序会每融15秒,做一次查询。

控制台输出

D:\workspace\javascript\nodejs-node-mysql>node app-reconnect.js
Wed Sep 11 2013 15:21:14 GMT+0800 (中国标准时间)
[ { Variable_name: 'wait_timeout', Value: '10' } ]
db error { [Error: Connection lost: The server closed the connection.] fatal: true, code: 'PROTOCOL_CONNECTION_LOST' }
Wed Sep 11 2013 15:21:28 GMT+0800 (中国标准时间)
[ { Variable_name: 'wait_timeout', Value: '10' } ]
db error { [Error: Connection lost: The server closed the connection.] fatal: true, code: 'PROTOCOL_CONNECTION_LOST' }
Wed Sep 11 2013 15:21:43 GMT+0800 (中国标准时间)
[ { Variable_name: 'wait_timeout', Value: '10' } ]

我们自己的程序捕获了“PROTOCOL_CONNECTION_LOST”异常,并自动的实现了数据库重连。

4). MySQL连接池的超时测试

针对wait_timeout问题,我们再对连接做一下测试。

修改app-pooling.js文件


var mysql = require('mysql');
var pool = mysql.createPool({
host: 'localhost',
user: 'nodejs',
password: 'nodejs',
database: 'nodejs',
port: 3306
}); var selectSQL ="show variables like 'wait_timeout'"; pool.getConnection(function (err, conn) {
if (err) console.log("POOL ==> " + err); function query(){
conn.query(selectSQL, function (err, res) {
console.log(new Date());
console.log(res);
conn.release();
});
}
query();
setInterval(query, 5000);
});

控制台输出:

D:\workspace\javascript\nodejs-node-mysql>node app-pooling.js
Wed Sep 11 2013 15:32:25 GMT+0800 (中国标准时间)
[ { Variable_name: 'wait_timeout', Value: '10' } ]
Wed Sep 11 2013 15:32:30 GMT+0800 (中国标准时间)
[ { Variable_name: 'wait_timeout', Value: '10' } ]
Wed Sep 11 2013 15:32:35 GMT+0800 (中国标准时间)
[ { Variable_name: 'wait_timeout', Value: '10' } ]

连接池,已经解决了自动重连的问题了,后面我们的开发,可以尽量使用pooling的方式。

转载请注明出处:
http://blog.fens.me/nodejs-mysql-intro/

转】用Nodejs连接MySQL的更多相关文章

  1. nodejs 连接 mysql 查询事务处理

    自己用 mysql 很多次的,然后又是主玩nodejs的.专门写一篇文章来说说nodejs连接mysql数据库.在使用之前,请检查计算机是否具有一下环境! nodejs 执行环境. mysql数据库环 ...

  2. Nodejs连接mysql

    1.首先需要安装nodejs 的mysql包 npm install mysql 2.编写nodejs与mysql交互的代码 var mysql = require('mysql'); var TES ...

  3. nodejs连接mysql并进行简单的增删查改

    最近在入门nodejs,正好学习到了如何使用nodejs进行数据库的连接,觉得比较重要,便写一下随笔,简单地记录一下 使用在安装好node之后,我们可以使用npm命令,在项目的根目录,安装nodejs ...

  4. nodejs连接mysql实例

    1.在工程目录下运行npm install mysql安装用于nodejs的mysql模块: 2.创建db.js模块用于连接mysql,同时定义query查询方法: var mysql = requi ...

  5. 用Nodejs连接MySQL

    转载,原地址:http://blog.fens.me/nodejs-mysql-intro/ 前言 MySQL是一款常用的开源数据库产品,通常也是免费数据库的首选.查了一下NPM列表,发现Nodejs ...

  6. Nodejs连接mysql的增、删、改、查操作

    一,创建数据库 Source Database : my_news_test SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- ...

  7. nodejs连接mysql数据库,报错Client does not support authentication protocol requested by server的解决方法

    最近想要尝试nodejs连接本地数据库,往全栈方向做一个小小的尝试,于是下载了一个 MySQL8.0,发现Navicat连接不上,结果就下载了mysql自身的Workbench,继续使用. 然而,难受 ...

  8. 使用nodejs连接mysql数据库实现增删改查

      首先要有数据库 使用xampp 或者 phpstudy 可以傻瓜式安装 新建一个项目文件夹 之后在这个目录下初始化package.json (npm init) 先在项目中安装mysql 和 ex ...

  9. nodejs连接mysql突然中断问题解决方案

    db/index.js数据库配置文件 一.在数据库连接失败的情况下,回调函数,再次发起连接,直到连接成功为止. handleDisconnect(){ this.connection.connect( ...

随机推荐

  1. centos 安装mysql时错误unknown variable 'defaults-file=/opt/redmine-2.6.0-2/mysql/my.cnf'

    找到my.cnf所在目录.运行 chmod 664 my.cnf,再启动mysql成功

  2. js 变量、函数提升

    js 变量.函数提升 先简单理解下作用域的概念,方便对变量与函数提升的概念的理解 function foo() { var x = 1; if (x) { var x = 2; } console.l ...

  3. 嵌入式linux 实现mdev SD卡和U盘自己主动挂载和卸载的方法 mdev.conf

    首先先參考这些博客做一些了解:http://linux.chinaunix.net/techdoc/install/2009/11/18/1144936.shtml http://www.cnblog ...

  4. myeclipse.hbm.xml自动生成

    第一,你的项目是否搭建了hibernate框架? 第二,你是否建立了相应的数据表: 第三,做好前两步,你再把myeclipse和数据库连接起来,在相应的表上点击右键,生成hibernate 关联文件就 ...

  5. java 内存简介

    java程序对内存分配的方式一般有三种: (1) 从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量. (2) 在栈上创建. 在执行函数时,函数内局 ...

  6. go---weichart个人对Golang中并发理解

    个人觉得goroutine是Go并行设计的核心,goroutine是协程,但比线程占用更少.golang对并发的处理采用了协程的技术.golang的goroutine就是协程的实现. 十几个gorou ...

  7. java操作CMD命令

    import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; public class CM ...

  8. problem in Sourcetree

    1.The date is commit date not the date of author 2.The log line is ordered  by time, actually it sho ...

  9. Android JNI MAC OS环境配置

    前言—JNI技术简介 JNI是Java Native Interface的缩写,即“Java本地调用”,它是Java世界和Native世界的中介桥梁.其中Native世界一般指C/C++的世界.众所周 ...

  10. python-----贴图 和 报错:OSError: image file is truncated (8 bytes not processed)的处理

    将一张图片贴到另一张图片上,代码如下: from PIL import Image import os from PIL import ImageFile ImageFile.LOAD_TRUNCAT ...