用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/

This entry was posted in Javascript语言实践数据库

Copyright © 2015 All rights reserved.
Designed by 

nodejs mysql 创建连接池的更多相关文章

  1. [nodejs]解决mysql和连接池(pool)自动断开问题

    最近在做一个个人项目,数据库尝试使用了mongodb.sqlite和mysql.分享一下关于mysql的连接池用法.项目部署于appfog,项目中我使用连接池链接数据库,本地测试一切正常.上线以后,经 ...

  2. Node.js使用MySQL的连接池

    使用Nodejs+MySQL肯定比PHP和MySQL的组合更适合做服务器端的开发. 使用Nodejs你会从他的异步行为中获益良多.比如,提升性能,你无须在从已有的MySQL数据库迁移到其他的NoSQL ...

  3. 使用代理创建连接池 proxyPool

    配置文件properties url=jdbc:mysql://127.0.0.1:3306/mine?characterEncoding=UTF-8 user=root password=1234 ...

  4. Java创建连接池连接不同数据库

    在一个应用里面,可能涉及到连接多个不同数据库进行操作,而每次连接写不同的实现会很麻烦.前面已经会了用JDBC连接数据库,那么利用反射和工厂模式,可以实现连接不同的数据库,这样处理起来将会很方便.同时建 ...

  5. Python下Mysql数据连接池——单例

    # coding:utf-8 import threading import pymysql from DBUtils.PooledDB import PooledDB from app.common ...

  6. Python 使用 PyMysql、DBUtils 创建连接池,提升性能

    转自:https://blog.csdn.net/weixin_41287692/article/details/83413775 Python 编程中可以使用 PyMysql 进行数据库的连接及诸如 ...

  7. MySQL 使用连接池封装pymysql

    备注:1,记得先修改连接的数据库哦,(用navicat更方便一点):2,分开两个py文件写入,运行sqlhelper.py文件 一.在utils.py中写 import pymysqlfrom DBU ...

  8. MySQL_(Java)【连接池】简单在JDBCUtils.java中创建连接池

    MySQL_(Java)[事物操作]使用JDBC模拟银行转账向数据库发起修改请求 传送门 MySQL_(Java)[连接池]使用DBCP简单模拟银行转账事物 传送门 Java应用程序访问数据库的过程: ...

  9. 码海拾遗:基于MySQL Connector/C++的MySQL操作(连接池)

    1.MySQL安装及简单设置 (1)安装:在OSX系统下,可以使用万能的“brew install”命令来进行安装:brew isntall mysql(默认安装最新版的MySQL) (2)启动:br ...

随机推荐

  1. Digit Division

    Digit Division Time limit: 1 s Memory limit: 512 MiB We are given a sequence of n decimal digits. Th ...

  2. 巨蟒python全栈开发linux之centos3

    1.作业讲解 (1)递归创建文件夹/tmp/oldboy/python/{alex,wusir,nvshen,xiaofeng} 下面中的路径没有必要换,在哪里创建都行,根目录下或者tmp目录下或者其 ...

  3. undefined let 作用域

    const o = {uid:123,pid:'wwww'}const wxPayNotifyUrlBizInfo = (o) => { // TODO json let s = '' for ...

  4. cmd文件和bat文件有什么区别

    第一次遇到后缀是cmd的文件, 记录下与bat文件的区别 本质上没有区别,都是简单的文本编码方式,都可以用记事本创建.编辑和查看. 两者所用的命令行代码也是共用的,只是cmd文件中允许使用的命令要比b ...

  5. 内置函数:sorted 用法

    内置函数——sorted  对list.dict进行排序,Python提供了两个方法 对给定的List L进行排序,方法1: 用List的成员函数sort进行排序,在本地进行排序,不返回副本方法2: ...

  6. 给俺的 CSDN 博客加背景音乐 - 高大尚的《心经》背景音乐

    给俺的 CSDN 博客加背景音乐 - 高大尚的<心经>背景音乐 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途- ...

  7. android自定义View (五)view.requestLayout() 与 invalidate()

    一.要点 If in the course of processing the event, the view's bounds may need to be changed, the view wi ...

  8. corethink功能模块探索开发(二)让这个模块可安装

    要想让这个模块可安装,只需要在opcmf.php文件中写一些配置数据就行 随便写点 Equip/opencmf.php <?php // 模块信息配置 return array( // 模块信息 ...

  9. Some day some time we will do

    Age has been reached the end of the beginning of the world,May be guilty in his seems to passing a l ...

  10. 【转】Python爬虫(6)_scrapy框架

    官网链接:https://docs.scrapy.org/en/latest/topics/architecture.html 性能相关 在编写爬虫时,性能的消耗主要在IO请求中,当单进程单线程模式下 ...