觸發器 tgr_dressNotice_insert 在插入後,透過游標遍歷多個分庫,動態構建 SQL 字串並呼叫遠端預存程序 spoa_exec_string 執行刪除/插入同步。錯誤訊息:
其他工作階段正在使用交易的內容(MSDTC 分散式交易衝突)。
linkedServer.dbo.table 或動態 SQL 呼叫遠端程序,且該連結伺服器**指向本機自身**(Loopback Linked Server)。
-- ❌ 原寫法:透過環回連結伺服器存取本機物件
SET @sSql = 'DELETE FROM ' + @LinkedServerName + '.dbo.dress_notice_config';
EXEC @RemoteProc @sSql;
-- ✅ 修正:直接使用本機三段式/兩段式名稱
SET @sSql = 'DELETE FROM dbo.dress_notice_config'; -- 同資料庫
-- 或跨資料庫:
SET @sSql = 'DELETE FROM OtherDB.dbo.dress_notice_config';
EXEC @LocalProc @sSql; -- 呼叫本機預存程序
LinkedServerName.dbo.物件 替換為 dbo.物件 或 DatabaseName.dbo.物件。DatabaseName.dbo.TableName,**不要建立指向自身的連結伺服器**。spoa_exec_string 若僅用於執行動態 SQL,可改為本機 sp_executesql 或直接在觸發器內執行(注意權限)。
CREATE TRIGGER tgr_dressNotice_insert
ON dress_notice_config
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE @TargetDB SYSNAME;
DECLARE @Sql NVARCHAR(MAX);
DECLARE db_cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT db_server FROM dic_organ
WHERE valid = '1' AND rank IN ('A','B') AND organ_id <> '000000';
OPEN db_cursor;
FETCH NEXT FROM db_cursor INTO @TargetDB;
WHILE @@FETCH_STATUS = 0
BEGIN
-- 同步刪除目標資料庫資料
SET @Sql = N'DELETE FROM ' + QUOTENAME(@TargetDB) + N'.dbo.dress_notice_config;';
EXEC sp_executesql @Sql; -- 本機執行,跨資料庫無需連結伺服器
-- 同步插入最新資料
SET @Sql = N'INSERT INTO ' + QUOTENAME(@TargetDB) + N'.dbo.dress_notice_config SELECT * FROM dbo.dress_notice_config;';
EXEC sp_executesql @Sql;
FETCH NEXT FROM db_cursor INTO @TargetDB;
END
CLOSE db_cursor;
DEALLOCATE db_cursor;
END
GO
sp_executesql + 參數化,防止注入並利用計畫快取。LOCAL FAST_FORWARD,僅供單向讀取,效能最佳。EXEC sp_linkedservers; 若發現指向自身的項目,**立即刪除**(EXEC sp_dropserver 'LoopbackName', 'droplogins';)。「其他工作階段正在使用交易內容」本質是 **環回連結伺服器觸發了不必要的分散式交易提升**。移除 Loopback Linked Server 參考、改用本機多資料庫三段式名稱,即可徹底解決。更進一步,建議將觸發器中的跨庫同步邏輯遷移至非同步機制,提升系統穩定度與擴展性。