mysql2连接池配置与优化

MySQL2 连接池配置与优化

MySQL2 是一个流行的 Node.js MySQL 客户端,支持连接池功能。连接池可以显著提升数据库性能,减少频繁创建和销毁连接的开销。

安装 MySQL2

bash 复制代码
npm install mysql2

基本连接池配置

javascript 复制代码
const mysql = require('mysql2/promise');

const pool = mysql.createPool({
  host: 'localhost',
  user: 'root',
  password: 'password',
  database: 'test',
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0
});

连接池关键参数详解

核心参数

  • connectionLimit: 连接池最大连接数,默认10
  • queueLimit: 等待队列的最大请求数,0表示无限制
  • waitForConnections: 当无可用连接时是否等待,默认true

性能优化参数

  • idleTimeout: 连接空闲超时时间(毫秒),默认60000
  • maxIdle: 最大空闲连接数,默认与connectionLimit相同
  • enableKeepAlive: 保持连接活性,默认false
  • keepAliveInitialDelay: 保持连接初始延迟(毫秒),默认0

高级优化策略

连接验证配置

javascript 复制代码
createPool({
  // ...其他配置
  testOnBorrow: true,
  validationQuery: 'SELECT 1'
});

超时控制

javascript 复制代码
createPool({
  // ...其他配置
  connectTimeout: 10000,
  acquireTimeout: 10000
});

SSL连接配置

javascript 复制代码
createPool({
  // ...其他配置
  ssl: {
    rejectUnauthorized: true,
    ca: fs.readFileSync(__dirname + '/mysql-ca.crt')
  }
});

连接池封装实践

基础封装示例

javascript 复制代码
class Database {
  constructor(config) {
    this.pool = mysql.createPool({
      ...config,
      connectionLimit: config.connectionLimit || 10,
      waitForConnections: true
    });
  }

  async query(sql, params) {
    const [rows] = await this.pool.query(sql, params);
    return rows;
  }

  async transaction(callback) {
    const conn = await this.pool.getConnection();
    try {
      await conn.beginTransaction();
      const result = await callback(conn);
      await conn.commit();
      return result;
    } catch (err) {
      await conn.rollback();
      throw err;
    } finally {
      conn.release();
    }
  }
}

高级封装方案

javascript 复制代码
class AdvancedDB {
  constructor(config) {
    this.config = {
      connectionLimit: 20,
      idleTimeout: 30000,
      ...config
    };
    this.initPool();
  }

  initPool() {
    this.pool = mysql.createPool(this.config);
    this.pool.on('connection', (conn) => {
      console.log('New connection established');
    });
    this.pool.on('acquire', (conn) => {
      console.log('Connection acquired');
    });
  }

  async execute(sql, params, conn) {
    const executor = conn || this.pool;
    try {
      const [rows] = await executor.query(sql, params);
      return rows;
    } catch (err) {
      console.error('Query failed:', err);
      throw err;
    }
  }

  async withTransaction(fn) {
    const conn = await this.pool.getConnection();
    try {
      await conn.beginTransaction();
      const result = await fn(conn);
      await conn.commit();
      return result;
    } catch (err) {
      await conn.rollback();
      throw err;
    } finally {
      conn.release();
    }
  }

  async close() {
    await this.pool.end();
  }
}

性能监控与调优

连接池状态监控

javascript 复制代码
// 定期检查连接池状态
setInterval(() => {
  console.log(`Active connections: ${pool._allConnections.length}`);
  console.log(`Idle connections: ${pool._freeConnections.length}`);
  console.log(`Waiting acquire: ${pool._acquiringConnections.length}`);
}, 5000);

动态调整参数

javascript 复制代码
// 根据负载动态调整连接池大小
function adjustPoolSize() {
  const load = getSystemLoad();
  if (load > 0.7) {
    pool.config.connectionLimit = Math.min(50, pool.config.connectionLimit + 5);
  } else {
    pool.config.connectionLimit = Math.max(10, pool.config.connectionLimit - 2);
  }
}

最佳实践建议

连接池大小计算

  • 公式:连接数 = (核心数 * 2) + 有效磁盘数
  • 对于CPU密集型应用可减少连接数
  • 对于I/O密集型应用可增加连接数

连接泄漏防护

javascript 复制代码
// 使用AsyncResource跟踪连接
const { AsyncResource } = require('async_hooks');

class TrackedConnection {
  constructor(conn) {
    this.resource = new AsyncResource('DBConnection');
    this.conn = conn;
  }

  query(sql, params) {
    return this.resource.runInAsyncScope(() => {
      return this.conn.query(sql, params);
    });
  }
}

连接预热策略

javascript 复制代码
// 应用启动时预热连接池
async function warmupPool(pool, count) {
  const connections = [];
  for (let i = 0; i < count; i++) {
    connections.push(pool.getConnection());
  }
  await Promise.all(connections);
  connections.forEach(conn => conn.release());
}

错误处理模式

重试机制实现

javascript 复制代码
async function queryWithRetry(sql, params, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      return await pool.query(sql, params);
    } catch (err) {
      if (i === retries - 1 || !isRetryableError(err)) throw err;
      await delay(100 * (i + 1));
    }
  }
}

function isRetryableError(err) {
  return err.code === 'ECONNRESET' || 
         err.code === 'ETIMEDOUT' ||
         err.code === 'PROTOCOL_SEQUENCE_TIMEOUT';
}

这些配置和优化策略可以帮助构建高性能、可靠的MySQL数据库连接池实现。实际应用中应根据具体业务场景和负载特点进行调整。

相关推荐
echome88828 分钟前
Python 异常处理:try、else、finally 的正确搭配
开发语言·前端·python·异常处理·编程技巧
时间的情敌32 分钟前
OpenLayers 实战|Vue3 + OpenLayers 完整工程案例(加载天地图、要素、弹窗、绘制、WFS)
前端·openlayers
陈随易33 分钟前
下载神器!Motrix 停更三年后重写回归
前端·后端·程序员
前端的日常1 小时前
一个人+AI做情侣食谱小程序,0 费用的服务器
前端·后端
计算机魔术师2 小时前
谷歌搜索广告踩刹车,AI广告成为救命稻草
前端
总要学点什么2 小时前
第81篇:数据可视化-PM2.5分布——让圆点的胖瘦替每座城市报出浓度
前端·信息可视化·echarts·cesium·空间分析
IT_陈寒2 小时前
Vue的v-for里用了个临时变量,页面直接挂了
前端·人工智能·后端
hunter_0762 小时前
一次 iOS 真机签名 409 的完整排查:证书、设备、描述文件为什么总是"对不上"
前端
枣把儿2 小时前
开源!公众号排版+一键发布工具懒人版
前端
2501_916007472 小时前
抓包工具功能对比,TraceEagle、Charles、Fiddler、Wireshark、mitmproxy 差别
前端·网络协议·ios·adb·https·fiddler·wireshark