Files
jurong_circle_black/database.js
2025-09-15 17:27:13 +08:00

159 lines
4.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<mysql.Pool>} 数据库连接池
*/
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<Array>} 查询结果
*/
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
};