const mysql = require('mysql2/promise'); // 数据库配置 const dbConfig = { // host: process.env.DB_HOST || '114.55.111.44', // user: process.env.DB_USER || 'maov2', // password: process.env.DB_PASSWORD || '5fYhw8z6T62b7heS', // database: process.env.DB_NAME || 'maov2', host: '114.55.111.44', user: 'test_mao', password: 'nK2mPbWriBp25BRd', database: 'test_mao', charset: 'utf8mb4', dateStrings: true, // 连接池配置 connectionLimit: 20, // 连接池最大连接数 // queueLimit: 0, // 排队等待连接的最大数量,0表示无限制 // 连接超时配置 // acquireTimeout: 60000, // 获取连接超时时间 60秒 // timeout: 60000, // 查询超时时间 60秒 // reconnect: true, // 自动重连 // 连接保活配置 // multipleStatements: true, // 空闲连接超时配置 // idleTimeout: 300000, // 5分钟空闲超时 // maxLifetime: 1800000, // 30分钟最大生命周期 // 连接保活设置 // keepAliveInitialDelay: 0, // 开始保活探测前的延迟时间 // enableKeepAlive: true, // 启用TCP保活 // 添加类型转换配置 typeCast: function (field, next) { if (field.type === 'TINY' && field.length === 1) { return (field.string() === '1'); // 1 = true, 0 = false } return next(); }, // 确保参数正确处理 supportBigNumbers: true, bigNumberStrings: false }; // 创建数据库连接池 let pool; /** * 初始化数据库连接池 * @returns {Promise} 数据库连接池 */ async function initDB() { if (!pool) { try { pool = mysql.createPool(dbConfig); // 添加连接池事件监听 pool.on('connection', function (connection) { console.log('新的数据库连接建立:', connection.threadId); }); // 注释掉频繁的连接获取和释放日志,避免日志过多 // pool.on('acquire', function (connection) { // console.log('连接池获取连接:', connection.threadId); // }); // pool.on('release', function (connection) { // console.log('连接池释放连接:', connection.threadId); // }); pool.on('error', function (err) { console.error('数据库连接池错误:', err); if (err.code === 'PROTOCOL_CONNECTION_LOST') { console.log('数据库连接丢失,尝试重新连接...'); } else if (err.code === 'ECONNRESET') { console.log('数据库连接被重置,尝试重新连接...'); } else if (err.code === 'ETIMEDOUT') { console.log('数据库连接超时,尝试重新连接...'); } }); // 测试连接 const connection = await pool.getConnection(); console.log('数据库连接池初始化成功'); connection.release(); } catch (error) { console.error('数据库连接池初始化失败:', error); throw error; } } return pool; } /** * 获取数据库连接池 * @returns {mysql.Pool} 数据库连接池 */ function getDB() { if (!pool) { throw new Error('数据库连接池未初始化,请先调用 initDB()'); } return pool; } /** * 执行数据库查询(带重试机制) * @param {string} sql SQL查询语句 * @param {Array} params 查询参数 * @param {number} retries 重试次数 * @returns {Promise} 查询结果 */ async function executeQuery(sql, params = [], retries = 3) { for (let i = 0; i < retries; i++) { try { const connection = await pool.getConnection(); try { const [results] = await connection.execute(sql, params); connection.release(); return results; } catch (error) { connection.release(); throw error; } } catch (error) { console.error(`数据库查询失败 (尝试 ${i + 1}/${retries}):`, error.message); if (i === retries - 1) { throw error; } // 如果是连接相关错误,等待后重试 if (error.code === 'PROTOCOL_CONNECTION_LOST' || error.code === 'ECONNRESET' || error.code === 'ETIMEDOUT') { console.log(`等待 ${(i + 1) * 1000}ms 后重试...`); await new Promise(resolve => setTimeout(resolve, (i + 1) * 1000)); } else { throw error; } } } } /** * 关闭数据库连接池 */ async function closeDB() { if (pool) { await pool.end(); pool = null; console.log('数据库连接池已关闭'); } } module.exports = { initDB, getDB, closeDB, executeQuery, dbConfig };