无论是node.js 还是 mysql 对我来说都并不陌生,然而我还真的是第一次将它们组合起来使用,初用node.js 的时候就接受了MongoDB,之后也很少用mysql了。
本文面向对 node.js 与 mysql 有基本了解,试图组合使用他们的读者(也包括我自己)。
安装
非常简单,准确地说并不是安装mysql数据库的本体,而是指mysql到nodejs的驱动程序。
使用 npm 在项目目录安装即可:
$ npm install mysql --save
连接
也是非常简单,先引入这个mysql包,然后调用 createConnection
方法来创建一个Connection对象。
参数细节可以参考:node mysql - Connection options
var mysql = require('mysql');
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'test'
});
现在这个 connection
还没有真正建立与数据库的连接。
你可以显式地调用 connection.connect()
来建立连接,或者:
// 查询所有的数据表
connection.query('show tables', (err, res) => console.log(err, res));
However, a connection can also be implicitly established by invoking a query
然而,数据库连接可以在调用查询时被隐式建立。—— node-mysql 文档
真是太方便啦!
连接管理
对于 node.js 应用而言,你大可不必在每次处理客户端请求的时候建立一个新的连接,然后在处理完毕的关闭这个连接。
你完全可以在整个 node.js 服务器运行时里面使用一个数据库连接,不用显式地调用 connection.close()
来关闭它,除非你确认这个连接在短时间内确实用不到了。
思考1:当node.js 服务器进程结束的时候,若不显式调用
connection.close()
,mysql服务器中的连接会变成僵尸进程吗?
不会。mysql服务器与 node.js 服务器之间使用 TCP 套接字来进行通讯,具有实时性1。即便 node.js 进程崩溃导致来不及进行任何扫尾工作,mysql服务器依然能够短时间内知道连接被断开了。思考2:为什么某些语言(如PHP)中需要显式地建立连接、关闭连接呢?
首先,连接无法被共享,PHP中程序跑完就跑完了,整个生命周期就那么短暂,你就算不显式关闭这个连接,其他的PHP进程也根本没有办法获取你的连接;其次,mysql进行垃圾连接的回收是需要一定额外代价的,高并发环境下,大量PHP进程建立大量连接,却不关闭它,这给mysql徒增了很多负担。
反观node.js,在整个服务器的运行时间下,通常至少以小时为单位的运行时间下,仅建立一个mysql连接,不关闭又怎么了嘛!均摊代价又有多少嘛!
模块化 工程化
利用 node.js 的模块管理,这样的封装可能是比较好的:
首先在根目录写一个 config.js
来保存一些全局性的配置(比如数据库的账号、密码等)。
然后建立一个db.js
专门用来声明数据库的连接。
然后再在其他的文件,例如test.js
中调用查询。
|- config.js
|- db.js
|- test.js
config.js
module.exports = {
db: {
host: 'localhost',
user: 'YOUR_USERNAME',
password: 'YOUR_PASSWORD',
database: 'YOUR_DATABASE_NAME'
}
};
db.js
var mysql = require('mysql');
var dbConfig = require('./config').db;
var connection = mysql.createConnection(dbConfig);
module.exports = connection;
对,我们只需要把这个 connection 对象导出就可以了。
test.js
var db = require('./db');
db.query('show processlist', (err, res) => console.log(err? err: res));
这个db.query
是不是特别地令人舒心?编写test.js
的时候根本不用管具体这个数据库是怎么连接的。
参考资料
- 实际上是利用 ping/pong 通讯的伪实时性,因此具有一定的延迟,具体视情况而定。 ↩