首先需要自己安装mysql数据库 不会的找一个集成包就可以
然后才能接着下面的事情~
建立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';
node-mysql安装
第一个测试
~ vi app.js var mysql = require('mysql'); var conn = mysql.createConnection({ host: 'localhost', user: '你的用户名 默认root', password: '你的mysql密码', 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 app.js The solution is: 2
此时已经说明已经正常链接到MySql了
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:workspacejavascript
odejs-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:workspacejavascript
odejs-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:workspacejavascript
odejs-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:workspacejavascript
odejs-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:workspacejavascript
odejs-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:workspacejavascript
odejs-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的方式。