0%

MySQL连接池

MySQL断线重连

分别模拟3种错误

登陆密码错误
数据库宕机
数据库连接超时
新增文件:app-reconnect.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
~ 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文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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的方式。