企業常需兩台伺服器運行相同資料庫,主機故障時快速切換備援機。傳統「發行-訂閱」複寫會導致訂閱端遺失觸發器、主鍵等物件,故障切換時仍需手動重建,維護負擔極重。本文提出基於 SQL Server 追蹤功能 (xp_trace_*) 的即時同步替代方案。
SQL Server 所有資料變更皆透過 T-SQL 敘述(INSERT/UPDATE/DELETE)完成。若能即時攔截特定資料庫的所有變更敘述,並重放至備援伺服器,即可實現邏輯層面的即時同步,且不受物件結構差異影響,甚至支援 Image 等大型欄位。
xp_trace_addnewqueue 建立追蹤佇列,設定事件類別(如 41 = SQL Batch Completed)。xp_trace_setdbidfilter、xp_trace_setappfilter、xp_trace_settextfilter 過濾目標資料庫與應用程式的變更敘述。xp_trace_setqueuedestination 將追蹤結果寫入本地資料表。bool TForm1::BuildTrace(int DBID, AnsiString AppFilter, AnsiString SQLFilter, AnsiString DstTable, int &TraceHandle)
{
char tempBuf[512];
Query1->Close(); Query1->SQL->Clear();
TStrings *pSQL = Query1->SQL;
pSQL->Add("USE master");
pSQL->Add("DECLARE @queue_handle int");
pSQL->Add("DECLARE @column_value int");
pSQL->Add("SET @column_value = 67108864|1|512|1024|10384");
pSQL->Add("EXEC xp_trace_addnewqueue 1000,5,95,90,@column_value,@queue_handle OUTPUT");
pSQL->Add("EXEC xp_trace_seteventclassrequired @queue_handle, 41,1");
wsprintf(tempBuf, "EXEC xp_trace_setappfilter @queue_handle,'%s',NULL", AppFilter.c_str());
pSQL->Add(AnsiString(tempBuf));
wsprintf(tempBuf, "EXEC xp_trace_setdbidfilter @queue_handle,%d", DBID);
pSQL->Add(AnsiString(tempBuf));
wsprintf(tempBuf, "Exec xp_trace_settextfilter @queue_handle,'%s',NULL", SQLFilter.c_str());
pSQL->Add(AnsiString(tempBuf));
wsprintf(tempBuf, "EXEC xp_trace_setqueuedestination @queue_handle,4,1,NULL,'%s'", DstTable.c_str());
pSQL->Add(AnsiString(tempBuf));
// ... 後續啟動追蹤與錯誤處理
}
此方案適合無法使用 AlwaysOn/鏡像/複寫的舊版環境,或需跨異構資料庫同步的場景。現代架構建議優先評估 AlwaysOn 可用性群組。