// ===================================================== // 資料庫連線監控工具 // ===================================================== import { db } from './database'; export class DatabaseMonitor { private static instance: DatabaseMonitor; private connectionCount = 0; private maxConnections = 0; private isMonitoring = false; private monitorInterval: NodeJS.Timeout | null = null; private constructor() {} public static getInstance(): DatabaseMonitor { if (!DatabaseMonitor.instance) { DatabaseMonitor.instance = new DatabaseMonitor(); } return DatabaseMonitor.instance; } // 開始監控 public startMonitoring(intervalMs: number = 30000) { if (this.isMonitoring) { console.log('⚠️ 資料庫監控已在運行中'); return; } this.isMonitoring = true; console.log('🔍 開始監控資料庫連線狀態...'); this.monitorInterval = setInterval(async () => { await this.checkConnectionStatus(); }, intervalMs); // 立即執行一次檢查 this.checkConnectionStatus(); } // 停止監控 public stopMonitoring() { if (this.monitorInterval) { clearInterval(this.monitorInterval); this.monitorInterval = null; } this.isMonitoring = false; console.log('⏹️ 資料庫監控已停止'); } // 檢查連線狀態 private async checkConnectionStatus() { let connection = null; try { // 使用單一連線來檢查狀態,避免建立多個連線 connection = await db.getConnection(); // 檢查當前連線數 const [statusResult] = await connection.execute(` SHOW STATUS LIKE 'Threads_connected' `); const currentConnections = statusResult[0]?.Value || 0; this.connectionCount = parseInt(currentConnections); // 檢查最大連線數 const [maxConnResult] = await connection.execute(` SHOW VARIABLES LIKE 'max_connections' `); this.maxConnections = parseInt(maxConnResult[0]?.Value || '100'); // 檢查連線使用率 const usagePercentage = (this.connectionCount / this.maxConnections) * 100; // 記錄狀態 console.log(`📊 資料庫連線狀態: ${this.connectionCount}/${this.maxConnections} (${usagePercentage.toFixed(1)}%)`); // 警告檢查 if (usagePercentage > 80) { console.warn(`⚠️ 資料庫連線使用率過高: ${usagePercentage.toFixed(1)}%`); } else if (usagePercentage > 60) { console.log(`⚠️ 資料庫連線使用率較高: ${usagePercentage.toFixed(1)}%`); } // 檢查長時間運行的查詢 await this.checkLongRunningQueries(connection); } catch (error) { console.error('❌ 資料庫監控錯誤:', error); } finally { // 確保釋放連線 if (connection) { try { connection.release(); } catch (releaseError) { console.error('❌ 釋放監控連線失敗:', releaseError); } } } } // 檢查長時間運行的查詢 private async checkLongRunningQueries(connection?: any) { try { // 如果沒有傳入連線,則建立一個新的 let tempConnection = connection; let shouldRelease = false; if (!tempConnection) { tempConnection = await db.getConnection(); shouldRelease = true; } try { const [longQueries] = await tempConnection.execute(` SELECT ID, USER, HOST, DB, COMMAND, TIME, STATE, INFO FROM information_schema.PROCESSLIST WHERE TIME > 30 AND COMMAND != 'Sleep' ORDER BY TIME DESC LIMIT 5 `); if (longQueries.length > 0) { console.warn(`⚠️ 發現 ${longQueries.length} 個長時間運行的查詢:`); longQueries.forEach((query: any, index: number) => { console.warn(` ${index + 1}. 用戶: ${query.USER}, 時間: ${query.TIME}s, 狀態: ${query.STATE}`); if (query.INFO && query.INFO.length > 100) { console.warn(` 查詢: ${query.INFO.substring(0, 100)}...`); } else if (query.INFO) { console.warn(` 查詢: ${query.INFO}`); } }); } } finally { // 只有當我們建立了新連線時才釋放 if (shouldRelease && tempConnection) { tempConnection.release(); } } } catch (error) { console.error('❌ 檢查長時間查詢時發生錯誤:', error); } } // 獲取連線統計 public getConnectionStats() { return { currentConnections: this.connectionCount, maxConnections: this.maxConnections, usagePercentage: (this.connectionCount / this.maxConnections) * 100, isMonitoring: this.isMonitoring }; } // 強制釋放空閒連線 public async releaseIdleConnections() { try { const result = await db.query(` KILL (SELECT GROUP_CONCAT(ID) FROM information_schema.PROCESSLIST WHERE COMMAND = 'Sleep' AND TIME > 300) `); console.log('🔄 已嘗試釋放空閒連線'); return true; } catch (error) { console.error('❌ 釋放空閒連線失敗:', error); return false; } } // 獲取連線池狀態 public getPoolStatus() { // 這裡可以添加更多連線池狀態信息 return { isMonitoring: this.isMonitoring, lastCheck: new Date().toISOString() }; } } // 導出單例實例 export const dbMonitor = DatabaseMonitor.getInstance();