為什麼這些來自不同 SQL Server 實例的 T-SQL 作業在同一個實例上執行(AlwaysOn 可用性組)
最近,我們的被阻止程序儀表板在我們進行統計更新時一直在報告被阻止的程序。
很快就找到了原因:在輔助和主 SQL Server 實例上都啟動了更新統計作業步驟 (T-SQL)。該作業更新同一數據庫上的多個統計資訊,該數據庫是 AlwaysOn 可用性組的一部分。我希望這會在輔助實例上失敗。
故障轉移歷史的簡要介紹:
伺服器 A 由於許可而應保持活動狀態(將被命名為活動伺服器),於 2002 年 2 月 20 日晚上 9 點意外故障轉移到伺服器 B(被動伺服器)。
在計劃外的故障轉移之後,我們在 2002 年 2 月 21 日下午 12 點進行了另一次(但這次是計劃的)手動故障轉移回活動伺服器。
工作經歷
在第一次故障轉移之前一切都很好,活動伺服器是唯一執行該作業的伺服器。
一項工作正在執行。 我們看到在活動端執行的統計更新。(當時是主副本)
在被動伺服器作為主副本的短時間內,我們沒有任何監控並且作業歷史被清除。
故障轉移後,回到“正常”狀態,在被動節點上的主節點上執行不到 24 小時後,被動實例上的作業步驟也已開始並在主動實例上執行。
現在對我來說有趣的部分是,這兩個作業都在活動伺服器上執行,看起來該作業正在使用偵聽器訪問數據庫。但這可能是一個完全不同的原因。
有一個複製作業 PowerShell 任務每晚在凌晨 1 點執行(dbatools):
powershell.exe Copy-DbaAgentJob -ExcludeJob "CopyJobs,CopyLogins" -Source INDCSPSQLA01 -Destination INDCSPSQLP01 -Force
我現在的猜測是針對一次,作業副本發生在帶有-Force 的主動輔助節點-> 主要被動節點。這發生在 21/02 上午 1 點。
問題
為什麼被動實例上的作業步驟在主動實例的數據庫上執行?
清單
在這兩種情況下,作業目標都是本地的:
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
伺服器名正確
select name from sys.servers select @@SERVERNAME
兩者都返回被動伺服器。
主動和被動的作業ID不同:
--08C63F07-0853-41DA-BC88-8FDF44AE491F -- passive --E8C88965-C581-4E06-B651-CC10637FCEEF -- active
這兩個作業在他們的步驟中都使用了有問題的數據庫:
@database_name=N'DB1',
–> 不應該在被動實例上訪問,導致失敗。 沒有可讀的次級
在被動實例上無法訪問數據庫:
兩台伺服器的版本:14.0.3030.27
T-SQL 作業步驟命令範例
@subsystem=N'TSQL', @command=N'update statistics dbo.table with fullscan ...'
作業開始時,被動實例上沒有任何執行。
編輯:
重新啟動被動節點上的代理“修復”此問題,導致執行時出現新錯誤:
無法連接到 SQL Server“INDCSPSQLP01”。步驟失敗。
因此,它不再更新主實例的統計資訊
申請資訊
SQLAgent - TSQL JobStep (Job 0x9D358B2EF6C53C4BAD6A61CA87D51BF5 : Step 1) SQLAgent - TSQL JobStep (Job 0x6589C8E881C5064EB651CC10637FCEEF : Step 1)
我沒有診斷出為什麼會出現這個問題,但是如果您有作業在可用性組中的數據庫上執行,最好在步驟 1 中包含一個檢查,該檢查使用該
fn_hadr_is_primary_replica
函式來檢查它是否在主數據庫上執行或次要的。IF (sys.fn_hadr_is_primary_replica('DB1') <> 1) BEGIN RAISERROR('%s is secondary', 11, 1, @@servername ); END
配置此步驟以在失敗時退出作業。這比嘗試執行失敗的東西要好,因為它會擊中輔助節點。