Files
jurong_circle_black/database.js

159 lines
4.9 KiB
JavaScript
Raw Normal View History

2025-08-26 10:06:23 +08:00
const mysql = require('mysql2/promise');
// 数据库配置
const dbConfig = {
2025-09-15 17:27:13 +08:00
// 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
2025-08-26 10:06:23 +08:00
};
// 创建数据库连接池
let pool;
/**
* 初始化数据库连接池
* @returns {Promise<mysql.Pool>} 数据库连接池
*/
async function initDB() {
2025-09-15 17:27:13 +08:00
if (!pool) {
try {
pool = mysql.createPool(dbConfig);
2025-08-26 10:06:23 +08:00
2025-09-15 17:27:13 +08:00
// 添加连接池事件监听
pool.on('connection', function (connection) {
console.log('新的数据库连接建立:', connection.threadId);
});
2025-08-26 10:06:23 +08:00
2025-09-15 17:27:13 +08:00
// 注释掉频繁的连接获取和释放日志,避免日志过多
// pool.on('acquire', function (connection) {
// console.log('连接池获取连接:', connection.threadId);
// });
2025-08-26 10:06:23 +08:00
2025-09-15 17:27:13 +08:00
// pool.on('release', function (connection) {
// console.log('连接池释放连接:', connection.threadId);
// });
2025-08-26 10:06:23 +08:00
2025-09-15 17:27:13 +08:00
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('数据库连接超时,尝试重新连接...');
}
});
2025-08-26 10:06:23 +08:00
2025-09-15 17:27:13 +08:00
// 测试连接
const connection = await pool.getConnection();
console.log('数据库连接池初始化成功');
connection.release();
2025-08-26 10:06:23 +08:00
2025-09-15 17:27:13 +08:00
} catch (error) {
console.error('数据库连接池初始化失败:', error);
throw error;
}
2025-08-26 10:06:23 +08:00
}
2025-09-15 17:27:13 +08:00
return pool;
2025-08-26 10:06:23 +08:00
}
/**
* 获取数据库连接池
* @returns {mysql.Pool} 数据库连接池
*/
function getDB() {
2025-09-15 17:27:13 +08:00
if (!pool) {
throw new Error('数据库连接池未初始化,请先调用 initDB()');
}
return pool;
2025-08-26 10:06:23 +08:00
}
/**
* 执行数据库查询带重试机制
* @param {string} sql SQL查询语句
* @param {Array} params 查询参数
* @param {number} retries 重试次数
* @returns {Promise<Array>} 查询结果
*/
async function executeQuery(sql, params = [], retries = 3) {
2025-09-15 17:27:13 +08:00
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;
}
}
2025-08-26 10:06:23 +08:00
}
}
/**
* 关闭数据库连接池
*/
async function closeDB() {
2025-09-15 17:27:13 +08:00
if (pool) {
await pool.end();
pool = null;
console.log('数据库连接池已关闭');
}
2025-08-26 10:06:23 +08:00
}
module.exports = {
2025-09-15 17:27:13 +08:00
initDB,
getDB,
closeDB,
executeQuery,
dbConfig
2025-08-26 10:06:23 +08:00
};