627 lines
22 KiB
JavaScript
627 lines
22 KiB
JavaScript
// =====================================================
|
||
// 修復的資料庫雙寫同步機制 (JavaScript 版本)
|
||
// 確保主機和備機使用各自的 ID 序列
|
||
// =====================================================
|
||
|
||
const mysql = require('mysql2/promise');
|
||
|
||
class DatabaseSyncFixed {
|
||
constructor() {
|
||
this.masterPool = null;
|
||
this.slavePool = null;
|
||
this.initializePools();
|
||
}
|
||
|
||
// 初始化連接池
|
||
initializePools() {
|
||
try {
|
||
// 主機連接池
|
||
this.masterPool = mysql.createPool({
|
||
host: process.env.DB_HOST || 'mysql.theaken.com',
|
||
port: parseInt(process.env.DB_PORT || '33306'),
|
||
user: process.env.DB_USER || 'AI_Platform',
|
||
password: process.env.DB_PASSWORD || 'Aa123456',
|
||
database: process.env.DB_NAME || 'db_AI_Platform',
|
||
charset: 'utf8mb4',
|
||
connectionLimit: 10
|
||
});
|
||
|
||
// 備機連接池
|
||
this.slavePool = mysql.createPool({
|
||
host: process.env.SLAVE_DB_HOST || '122.100.99.161',
|
||
port: parseInt(process.env.SLAVE_DB_PORT || '43306'),
|
||
user: process.env.SLAVE_DB_USER || 'A999',
|
||
password: process.env.SLAVE_DB_PASSWORD || '1023',
|
||
database: process.env.SLAVE_DB_NAME || 'db_AI_Platform',
|
||
charset: 'utf8mb4',
|
||
connectionLimit: 10
|
||
});
|
||
|
||
console.log('✅ 修復的雙寫連接池初始化成功');
|
||
} catch (error) {
|
||
console.error('❌ 修復的雙寫連接池初始化失敗:', error);
|
||
}
|
||
}
|
||
|
||
// 智能雙寫插入 - 每個資料庫使用自己的 ID
|
||
async smartDualInsert(tableName, data) {
|
||
const result = {
|
||
success: false,
|
||
masterSuccess: false,
|
||
slaveSuccess: false
|
||
};
|
||
|
||
try {
|
||
// 同時寫入主機和備機,各自生成 ID
|
||
const masterPromise = this.insertToMaster(tableName, data);
|
||
const slavePromise = this.insertToSlave(tableName, data);
|
||
|
||
const [masterResult, slaveResult] = await Promise.allSettled([masterPromise, slavePromise]);
|
||
|
||
result.masterSuccess = masterResult.status === 'fulfilled';
|
||
result.slaveSuccess = slaveResult.status === 'fulfilled';
|
||
result.success = result.masterSuccess || result.slaveSuccess;
|
||
|
||
if (masterResult.status === 'fulfilled') {
|
||
result.masterId = masterResult.value;
|
||
} else {
|
||
result.masterError = masterResult.reason instanceof Error ? masterResult.reason.message : '主機寫入失敗';
|
||
}
|
||
|
||
if (slaveResult.status === 'fulfilled') {
|
||
result.slaveId = slaveResult.value;
|
||
} else {
|
||
result.slaveError = slaveResult.reason instanceof Error ? slaveResult.reason.message : '備機寫入失敗';
|
||
}
|
||
|
||
console.log(`📝 智能雙寫結果: 主機${result.masterSuccess ? '✅' : '❌'} 備機${result.slaveSuccess ? '✅' : '❌'}`);
|
||
|
||
} catch (error) {
|
||
result.masterError = error instanceof Error ? error.message : '智能雙寫執行失敗';
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
// 寫入主機 - 使用主機的 ID 生成
|
||
async insertToMaster(tableName, data) {
|
||
if (!this.masterPool) {
|
||
throw new Error('主機連接池不可用');
|
||
}
|
||
|
||
const connection = await this.masterPool.getConnection();
|
||
try {
|
||
// 生成主機的 UUID
|
||
const [uuidResult] = await connection.execute('SELECT UUID() as id');
|
||
const masterId = uuidResult[0].id;
|
||
|
||
// 構建插入 SQL
|
||
const columns = Object.keys(data).join(', ');
|
||
const placeholders = Object.keys(data).map(() => '?').join(', ');
|
||
const values = Object.values(data);
|
||
|
||
const sql = `INSERT INTO ${tableName} (id, ${columns}) VALUES (?, ${placeholders})`;
|
||
await connection.execute(sql, [masterId, ...values]);
|
||
|
||
console.log(`✅ 主機寫入成功: ${masterId}`);
|
||
return masterId;
|
||
} finally {
|
||
connection.release();
|
||
}
|
||
}
|
||
|
||
// 寫入備機 - 使用備機的 ID 生成
|
||
async insertToSlave(tableName, data) {
|
||
if (!this.slavePool) {
|
||
throw new Error('備機連接池不可用');
|
||
}
|
||
|
||
const connection = await this.slavePool.getConnection();
|
||
try {
|
||
// 生成備機的 UUID
|
||
const [uuidResult] = await connection.execute('SELECT UUID() as id');
|
||
const slaveId = uuidResult[0].id;
|
||
|
||
// 構建插入 SQL
|
||
const columns = Object.keys(data).join(', ');
|
||
const placeholders = Object.keys(data).map(() => '?').join(', ');
|
||
const values = Object.values(data);
|
||
|
||
const sql = `INSERT INTO ${tableName} (id, ${columns}) VALUES (?, ${placeholders})`;
|
||
await connection.execute(sql, [slaveId, ...values]);
|
||
|
||
console.log(`✅ 備機寫入成功: ${slaveId}`);
|
||
return slaveId;
|
||
} finally {
|
||
connection.release();
|
||
}
|
||
}
|
||
|
||
// 智能雙寫更新
|
||
async smartDualUpdate(tableName, id, updates) {
|
||
const result = {
|
||
success: false,
|
||
masterSuccess: false,
|
||
slaveSuccess: false
|
||
};
|
||
|
||
try {
|
||
// 先獲取主機的記錄
|
||
const masterRecord = await this.getMasterRecord(tableName, id);
|
||
|
||
if (!masterRecord) {
|
||
throw new Error('主機記錄不存在');
|
||
}
|
||
|
||
// 獲取備機的記錄 ID(通過名稱匹配)
|
||
const slaveId = await this.getSlaveRecordIdByName(tableName, masterRecord.name);
|
||
|
||
if (!slaveId) {
|
||
throw new Error('備機記錄不存在');
|
||
}
|
||
|
||
// 同時更新主機和備機
|
||
const masterPromise = this.updateMasterRecord(tableName, id, updates);
|
||
const slavePromise = this.updateSlaveRecord(tableName, slaveId, updates);
|
||
|
||
const [masterResult, slaveResult] = await Promise.allSettled([masterPromise, slavePromise]);
|
||
|
||
result.masterSuccess = masterResult.status === 'fulfilled';
|
||
result.slaveSuccess = slaveResult.status === 'fulfilled';
|
||
result.success = result.masterSuccess || result.slaveSuccess;
|
||
|
||
if (masterResult.status === 'rejected') {
|
||
result.masterError = masterResult.reason instanceof Error ? masterResult.reason.message : '主機更新失敗';
|
||
}
|
||
if (slaveResult.status === 'rejected') {
|
||
result.slaveError = slaveResult.reason instanceof Error ? slaveResult.reason.message : '備機更新失敗';
|
||
}
|
||
|
||
} catch (error) {
|
||
result.masterError = error instanceof Error ? error.message : '雙寫更新執行失敗';
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
// 智能雙寫關聯表 - 使用對應的競賽 ID
|
||
async smartDualInsertRelation(relationTable, masterCompetitionId, slaveCompetitionId, relationData, relationIdField) {
|
||
const result = {
|
||
success: false,
|
||
masterSuccess: false,
|
||
slaveSuccess: false
|
||
};
|
||
|
||
try {
|
||
console.log(`🔍 關聯雙寫開始: ${relationTable}`);
|
||
console.log(` 主機競賽 ID: ${masterCompetitionId}`);
|
||
console.log(` 備機競賽 ID: ${slaveCompetitionId}`);
|
||
console.log(` 關聯數據數量: ${relationData.length}`);
|
||
|
||
// 先驗證競賽 ID 是否存在
|
||
const masterExists = await this.verifyCompetitionExists(masterCompetitionId, 'master');
|
||
const slaveExists = await this.verifyCompetitionExists(slaveCompetitionId, 'slave');
|
||
|
||
console.log(` 主機競賽存在: ${masterExists}`);
|
||
console.log(` 備機競賽存在: ${slaveExists}`);
|
||
|
||
if (!masterExists) {
|
||
result.masterError = '主機競賽不存在';
|
||
result.slaveError = '主機競賽不存在,跳過備機寫入';
|
||
console.log(`📝 關聯雙寫結果: 主機❌ 備機❌`);
|
||
return result;
|
||
}
|
||
|
||
if (!slaveExists) {
|
||
result.masterError = '備機競賽不存在';
|
||
result.slaveError = '備機競賽不存在';
|
||
console.log(`📝 關聯雙寫結果: 主機❌ 備機❌`);
|
||
return result;
|
||
}
|
||
|
||
// 同時寫入關聯數據
|
||
const masterPromise = this.insertRelationsToMaster(relationTable, masterCompetitionId, relationData, relationIdField);
|
||
const slavePromise = this.insertRelationsToSlave(relationTable, slaveCompetitionId, relationData, relationIdField);
|
||
|
||
const [masterResult, slaveResult] = await Promise.allSettled([masterPromise, slavePromise]);
|
||
|
||
result.masterSuccess = masterResult.status === 'fulfilled';
|
||
result.slaveSuccess = slaveResult.status === 'fulfilled';
|
||
result.success = result.masterSuccess || result.slaveSuccess;
|
||
|
||
if (masterResult.status === 'rejected') {
|
||
result.masterError = masterResult.reason instanceof Error ? masterResult.reason.message : '主機關聯寫入失敗';
|
||
}
|
||
if (slaveResult.status === 'rejected') {
|
||
result.slaveError = slaveResult.reason instanceof Error ? slaveResult.reason.message : '備機關聯寫入失敗';
|
||
}
|
||
|
||
console.log(`📝 關聯雙寫結果: 主機${result.masterSuccess ? '✅' : '❌'} 備機${result.slaveSuccess ? '✅' : '❌'}`);
|
||
|
||
} catch (error) {
|
||
result.masterError = error instanceof Error ? error.message : '關聯雙寫執行失敗';
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
// 驗證競賽是否存在
|
||
async verifyCompetitionExists(competitionId, database) {
|
||
try {
|
||
const pool = database === 'master' ? this.masterPool : this.slavePool;
|
||
if (!pool) return false;
|
||
|
||
const connection = await pool.getConnection();
|
||
try {
|
||
const [rows] = await connection.execute('SELECT COUNT(*) as count FROM competitions WHERE id = ?', [competitionId]);
|
||
return rows[0].count > 0;
|
||
} finally {
|
||
connection.release();
|
||
}
|
||
} catch (error) {
|
||
console.error(`驗證${database}競賽存在失敗:`, error.message);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 獲取備機的評審 ID(通過名稱匹配)
|
||
async getSlaveJudgeId(masterJudgeId) {
|
||
try {
|
||
if (!this.slavePool) return masterJudgeId;
|
||
|
||
const connection = await this.slavePool.getConnection();
|
||
try {
|
||
// 先獲取主機評審的名稱
|
||
const masterConn = await this.masterPool.getConnection();
|
||
const [masterJudge] = await masterConn.execute('SELECT name FROM judges WHERE id = ?', [masterJudgeId]);
|
||
masterConn.release();
|
||
|
||
if (masterJudge.length === 0) return masterJudgeId;
|
||
|
||
// 在備機中查找相同名稱的評審
|
||
const [slaveJudges] = await connection.execute('SELECT id FROM judges WHERE name = ? ORDER BY created_at ASC LIMIT 1', [masterJudge[0].name]);
|
||
|
||
return slaveJudges.length > 0 ? slaveJudges[0].id : masterJudgeId;
|
||
} finally {
|
||
connection.release();
|
||
}
|
||
} catch (error) {
|
||
console.error('獲取備機評審 ID 失敗:', error);
|
||
return masterJudgeId;
|
||
}
|
||
}
|
||
|
||
// 獲取備機的團隊 ID(通過名稱匹配)
|
||
async getSlaveTeamId(masterTeamId) {
|
||
try {
|
||
if (!this.slavePool) return masterTeamId;
|
||
|
||
const connection = await this.slavePool.getConnection();
|
||
try {
|
||
// 先獲取主機團隊的名稱
|
||
const masterConn = await this.masterPool.getConnection();
|
||
const [masterTeam] = await masterConn.execute('SELECT name FROM teams WHERE id = ?', [masterTeamId]);
|
||
masterConn.release();
|
||
|
||
if (masterTeam.length === 0) return masterTeamId;
|
||
|
||
// 在備機中查找相同名稱的團隊
|
||
const [slaveTeams] = await connection.execute('SELECT id FROM teams WHERE name = ? ORDER BY created_at ASC LIMIT 1', [masterTeam[0].name]);
|
||
|
||
return slaveTeams.length > 0 ? slaveTeams[0].id : masterTeamId;
|
||
} finally {
|
||
connection.release();
|
||
}
|
||
} catch (error) {
|
||
console.error('獲取備機團隊 ID 失敗:', error);
|
||
return masterTeamId;
|
||
}
|
||
}
|
||
|
||
// 寫入主機關聯表
|
||
async insertRelationsToMaster(relationTable, competitionId, relationData, relationIdField) {
|
||
if (!this.masterPool) return;
|
||
|
||
const connection = await this.masterPool.getConnection();
|
||
try {
|
||
for (const data of relationData) {
|
||
const [uuidResult] = await connection.execute('SELECT UUID() as id');
|
||
const relationId = uuidResult[0].id;
|
||
|
||
if (relationTable === 'competition_award_types') {
|
||
// 特殊處理獎項類型
|
||
const sql = `INSERT INTO ${relationTable} (id, competition_id, name, description, icon, color, order_index) VALUES (?, ?, ?, ?, ?, ?, ?)`;
|
||
await connection.execute(sql, [
|
||
relationId,
|
||
competitionId,
|
||
data.name,
|
||
data.description || '',
|
||
data.icon || '🏆',
|
||
data.color || 'text-yellow-600',
|
||
data.order_index || 0
|
||
]);
|
||
} else if (relationTable === 'competition_rules') {
|
||
// 特殊處理評分規則
|
||
const sql = `INSERT INTO ${relationTable} (id, competition_id, name, description, weight, order_index) VALUES (?, ?, ?, ?, ?, ?)`;
|
||
await connection.execute(sql, [
|
||
relationId,
|
||
competitionId,
|
||
data.name,
|
||
data.description || '',
|
||
data.weight || 0,
|
||
data.order_index || 0
|
||
]);
|
||
} else {
|
||
// 一般關聯表
|
||
const sql = `INSERT INTO ${relationTable} (id, competition_id, ${relationIdField}) VALUES (?, ?, ?)`;
|
||
await connection.execute(sql, [relationId, competitionId, data[relationIdField]]);
|
||
}
|
||
}
|
||
} finally {
|
||
connection.release();
|
||
}
|
||
}
|
||
|
||
// 寫入備機關聯表
|
||
async insertRelationsToSlave(relationTable, competitionId, relationData, relationIdField) {
|
||
if (!this.slavePool) return;
|
||
|
||
const connection = await this.slavePool.getConnection();
|
||
try {
|
||
// 先刪除現有的關聯數據
|
||
await connection.execute(`DELETE FROM ${relationTable} WHERE competition_id = ?`, [competitionId]);
|
||
|
||
for (const data of relationData) {
|
||
const [uuidResult] = await connection.execute('SELECT UUID() as id');
|
||
const relationId = uuidResult[0].id;
|
||
|
||
if (relationTable === 'competition_award_types') {
|
||
// 特殊處理獎項類型
|
||
const sql = `INSERT INTO ${relationTable} (id, competition_id, name, description, icon, color, order_index) VALUES (?, ?, ?, ?, ?, ?, ?)`;
|
||
await connection.execute(sql, [
|
||
relationId,
|
||
competitionId,
|
||
data.name,
|
||
data.description || '',
|
||
data.icon || '🏆',
|
||
data.color || 'text-yellow-600',
|
||
data.order_index || 0
|
||
]);
|
||
} else if (relationTable === 'competition_rules') {
|
||
// 特殊處理評分規則
|
||
const sql = `INSERT INTO ${relationTable} (id, competition_id, name, description, weight, order_index) VALUES (?, ?, ?, ?, ?, ?)`;
|
||
await connection.execute(sql, [
|
||
relationId,
|
||
competitionId,
|
||
data.name,
|
||
data.description || '',
|
||
data.weight || 0,
|
||
data.order_index || 0
|
||
]);
|
||
} else {
|
||
// 一般關聯表 - 處理 ID 映射
|
||
let slaveId = data[relationIdField];
|
||
|
||
if (relationTable === 'competition_judges' && relationIdField === 'judge_id') {
|
||
slaveId = await this.getSlaveJudgeId(data[relationIdField]);
|
||
} else if (relationTable === 'competition_teams' && relationIdField === 'team_id') {
|
||
slaveId = await this.getSlaveTeamId(data[relationIdField]);
|
||
}
|
||
|
||
const sql = `INSERT INTO ${relationTable} (id, competition_id, ${relationIdField}) VALUES (?, ?, ?)`;
|
||
await connection.execute(sql, [relationId, competitionId, slaveId]);
|
||
}
|
||
}
|
||
} finally {
|
||
connection.release();
|
||
}
|
||
}
|
||
|
||
// 獲取主機記錄
|
||
async getMasterRecord(tableName, id) {
|
||
if (!this.masterPool) return null;
|
||
|
||
const connection = await this.masterPool.getConnection();
|
||
try {
|
||
const [rows] = await connection.execute(`SELECT * FROM ${tableName} WHERE id = ?`, [id]);
|
||
return rows[0] || null;
|
||
} finally {
|
||
connection.release();
|
||
}
|
||
}
|
||
|
||
// 根據名稱獲取備機記錄 ID
|
||
async getSlaveRecordIdByName(tableName, name) {
|
||
if (!this.slavePool) return null;
|
||
|
||
const connection = await this.slavePool.getConnection();
|
||
try {
|
||
const [rows] = await connection.execute(`SELECT id FROM ${tableName} WHERE name = ? ORDER BY created_at DESC LIMIT 1`, [name]);
|
||
const result = rows[0]?.id || null;
|
||
return result && typeof result !== 'string' ? String(result) : result;
|
||
} finally {
|
||
connection.release();
|
||
}
|
||
}
|
||
|
||
// 更新主機記錄
|
||
async updateMasterRecord(tableName, id, updates) {
|
||
if (!this.masterPool) return;
|
||
|
||
const fields = Object.keys(updates).filter(key => key !== 'id' && key !== 'created_at');
|
||
if (fields.length === 0) return;
|
||
|
||
const setClause = fields.map(field => `${field} = ?`).join(', ');
|
||
const values = fields.map(field => updates[field]);
|
||
|
||
const connection = await this.masterPool.getConnection();
|
||
try {
|
||
const sql = `UPDATE ${tableName} SET ${setClause}, updated_at = CURRENT_TIMESTAMP WHERE id = ?`;
|
||
await connection.execute(sql, [...values, id]);
|
||
} finally {
|
||
connection.release();
|
||
}
|
||
}
|
||
|
||
// 更新備機記錄
|
||
async updateSlaveRecord(tableName, id, updates) {
|
||
if (!this.slavePool) return;
|
||
|
||
const fields = Object.keys(updates).filter(key => key !== 'id' && key !== 'created_at');
|
||
if (fields.length === 0) return;
|
||
|
||
const setClause = fields.map(field => `${field} = ?`).join(', ');
|
||
const values = fields.map(field => updates[field]);
|
||
|
||
const connection = await this.slavePool.getConnection();
|
||
try {
|
||
const sql = `UPDATE ${tableName} SET ${setClause}, updated_at = CURRENT_TIMESTAMP WHERE id = ?`;
|
||
await connection.execute(sql, [...values, id]);
|
||
} finally {
|
||
connection.release();
|
||
}
|
||
}
|
||
|
||
// 清除所有競賽的當前狀態
|
||
async clearAllCurrentCompetitions() {
|
||
const result = {
|
||
success: false,
|
||
masterSuccess: false,
|
||
slaveSuccess: false
|
||
};
|
||
|
||
try {
|
||
// 同時清除主機和備機的所有當前競賽狀態
|
||
const masterPromise = this.clearMasterCurrentCompetitions();
|
||
const slavePromise = this.clearSlaveCurrentCompetitions();
|
||
|
||
const [masterResult, slaveResult] = await Promise.allSettled([masterPromise, slavePromise]);
|
||
|
||
result.masterSuccess = masterResult.status === 'fulfilled';
|
||
result.slaveSuccess = slaveResult.status === 'fulfilled';
|
||
result.success = result.masterSuccess || result.slaveSuccess;
|
||
|
||
if (masterResult.status === 'rejected') {
|
||
result.masterError = masterResult.reason instanceof Error ? masterResult.reason.message : '主機清除失敗';
|
||
}
|
||
if (slaveResult.status === 'rejected') {
|
||
result.slaveError = slaveResult.reason instanceof Error ? slaveResult.reason.message : '備機清除失敗';
|
||
}
|
||
|
||
} catch (error) {
|
||
result.masterError = error instanceof Error ? error.message : '清除所有當前競賽執行失敗';
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
// 清除主機的所有當前競賽狀態
|
||
async clearMasterCurrentCompetitions() {
|
||
if (!this.masterPool) return;
|
||
|
||
const connection = await this.masterPool.getConnection();
|
||
try {
|
||
await connection.execute('UPDATE competitions SET is_current = FALSE');
|
||
} finally {
|
||
connection.release();
|
||
}
|
||
}
|
||
|
||
// 清除備機的所有當前競賽狀態
|
||
async clearSlaveCurrentCompetitions() {
|
||
if (!this.slavePool) return;
|
||
|
||
const connection = await this.slavePool.getConnection();
|
||
try {
|
||
await connection.execute('UPDATE competitions SET is_current = FALSE');
|
||
} finally {
|
||
connection.release();
|
||
}
|
||
}
|
||
|
||
// 智能雙寫刪除
|
||
async smartDualDelete(tableName, id, idField = 'id') {
|
||
const result = {
|
||
success: false,
|
||
masterSuccess: false,
|
||
slaveSuccess: false
|
||
};
|
||
|
||
try {
|
||
// 獲取備機對應的 ID
|
||
let slaveId = null;
|
||
if (tableName === 'competitions') {
|
||
// 對於競賽表,先獲取競賽名稱
|
||
const masterRecord = await this.getMasterRecord(tableName, id);
|
||
if (masterRecord) {
|
||
slaveId = await this.getSlaveRecordIdByName(tableName, masterRecord.name);
|
||
}
|
||
} else {
|
||
// 對於關聯表,直接使用主機 ID
|
||
slaveId = id;
|
||
}
|
||
|
||
// 同時刪除主機和備機的記錄
|
||
const masterPromise = this.deleteFromMaster(tableName, id, idField);
|
||
const slavePromise = slaveId ? this.deleteFromSlave(tableName, slaveId, idField) : Promise.resolve();
|
||
|
||
const [masterResult, slaveResult] = await Promise.allSettled([masterPromise, slavePromise]);
|
||
|
||
result.masterSuccess = masterResult.status === 'fulfilled';
|
||
result.slaveSuccess = slaveResult.status === 'fulfilled';
|
||
result.success = result.masterSuccess || result.slaveSuccess;
|
||
|
||
if (masterResult.status === 'rejected') {
|
||
result.masterError = masterResult.reason instanceof Error ? masterResult.reason.message : '主機刪除失敗';
|
||
}
|
||
if (slaveResult.status === 'rejected') {
|
||
result.slaveError = slaveResult.reason instanceof Error ? slaveResult.reason.message : '備機刪除失敗';
|
||
}
|
||
|
||
} catch (error) {
|
||
result.masterError = error instanceof Error ? error.message : '雙寫刪除執行失敗';
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
// 從主機刪除記錄
|
||
async deleteFromMaster(tableName, id, idField = 'id') {
|
||
if (!this.masterPool) return;
|
||
|
||
const connection = await this.masterPool.getConnection();
|
||
try {
|
||
const sql = `DELETE FROM ${tableName} WHERE ${idField} = ?`;
|
||
await connection.execute(sql, [id]);
|
||
} finally {
|
||
connection.release();
|
||
}
|
||
}
|
||
|
||
// 從備機刪除記錄
|
||
async deleteFromSlave(tableName, id, idField = 'id') {
|
||
if (!this.slavePool) return;
|
||
|
||
const connection = await this.slavePool.getConnection();
|
||
try {
|
||
const sql = `DELETE FROM ${tableName} WHERE ${idField} = ?`;
|
||
await connection.execute(sql, [id]);
|
||
} finally {
|
||
connection.release();
|
||
}
|
||
}
|
||
|
||
// 清理資源
|
||
async close() {
|
||
if (this.masterPool) {
|
||
await this.masterPool.end();
|
||
}
|
||
if (this.slavePool) {
|
||
await this.slavePool.end();
|
||
}
|
||
}
|
||
}
|
||
|
||
// 導出實例
|
||
module.exports = { DatabaseSyncFixed };
|