记一次MySQL数据库问题排查

发表于:2016-4-11 10:46

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:KohPoll    来源:51Testing软件测试网采编

  最近遇到应用频繁的响应缓慢,无法正常访问。帮忙一起定位原因,最后定位到的问题说起来真的是很小的细节问题,但是就是这些小细节导致了服务不稳定,真是细节决定成败。这里尝试着来分享下,希望对大家有所帮助。
  问题 1:占着茅坑不拉屎
  遇到问题首先要看的还是服务器错误日志。
  错误日志中看到频繁有这样的一个异常报错:Error: ER_CON_COUNT_ERROR: Too many connections。这个报错是因为数据库的所有连接被客户端都占有了,没有空闲的连接可以使用。MySQL 默认的最大并发连接数是 100,然而我们的应用这边最多可能的并发也就 30~40 个任务,怎么也不太可能报这样的错误,推测很有可能是代码里面建立连接后没有及时的进行关闭。于是我们重点看了下执行 SQL 部分的代码,大概是下面这样(使用了node-mysql库):
var mysql = require('mysql');
// 建立连接池
var pool = mysql.createPool({
host: 'host',
user: 'user',
password: 'password',
database: 'db'
});
exports.query = function(sql, cb) {
// 从池子里面取一个可用连接
pool.getConnection(function(err, connection) {
if (err) throw err;
// 执行sql
connection.query(sql, function(err, rows, fields) {
if (err) {
return cosole.error(err);
}
cb(rows);
});
// 释放此连接
connection.release();
});
};
  刚开始我还真没看出来有什么问题,后来仔细读了 node-mysql 的文档及这个 issue,终于发现了我们的写法是有问题的。
  再次看看上面的代码,pool.getConnection 后我们执行 connection.query,然后没等 SQL 执行完,直接调用了 connection.release,由于 JavaScript 的异步特性(虽然 SQL 可能很快就执行完,但是我们也必须在 connection.query 的 callback 里面才明确的知道 SQL 执行完了),这个时候此次连接是不会被释放的!代码里面所有的 SQL 执行都调用到这个函数,这意味着我们占着一堆数据库连接不释放,这时不断的有其他数据库连接过来,直接导致其他连接被阻塞,抛出连接太多的异常。这真是典型的“拉完不及时让坑,占着茅坑不拉屎”的行为。所以,我们一定要在 SQL 执行完成后就将连接及时进行释放。因为 SQL 执行一般是非常快的(零点几秒),如果我们执行完后不释放,在同一时间产生很多数据库连接时很有可能导致连接被阻塞,产生连接过多的异常。于是我们对代码进行了如下修改:
exports.query = function(sql, cb) {
// 从池子里面取一个可用连接
pool.getConnection(function(err, connection) {
if (err) throw err;
// 执行sql
connection.query(sql, function(err, rows, fields) {
// 释放连接(一定要在错误处理前,不然出错的时候也会导致该连接得不到释放)
connection.release();
if (err) {
return cosole.error(err);
}
cb(rows);
});
});
};
  也可以用更简单的写法 pool.query,这个方法内部会在合适的时机来释放连接,不用我们手动操作。
  完成此次修改后,这个异常没有再复现,但是响应缓慢的情况依然没有得到缓解。
21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号