一、SQL Server對等復制沖突產生的原因
在單個數據庫環境下,不同應用程序對於同一張表中的同一條記錄進行更改一般不會產生沖突。這主要是因為在數據庫中已經實現了鎖的機制,來避免這種沖突的產生。但是在異步分布式數據庫環境中,每個事務獨立作用於每個節點。最要命的是,在2008之前,沒有用來跨越多個節點對事務進行序列化的機制。在以前的數據庫版本中,主要是通過使用連階段提交等控制機制,來避免這種沖突。但是這種機制並不是很好,因為其會影響到數據庫的性能。
如上圖所示,某個集團有三個服務器用來做OA系統的服務器,分別部署在三個不同的分支機構。此時,有可能A服務器所在的公司往用戶表中插入一條記錄,其員工編號為PR010;同時B服務器所在公司也同時往用戶表中插入一條記錄,員工編號也為PR010。而這個員工編號的字段在表中設置為關鍵字。此時就會出現沖突。在對等復制服務器中,在單個對等節點(如服務器A)上提交更改之後將檢測不到沖突。但是,在復制這些更改並將其應用於其它對等節點之後(如A服務器中的數據復制到集團服務器,然後集團服務器再將其應用與服務器B),才能夠檢測到這些更改。在2008版本以前的數據庫中,針對這種情況沒有很好的處理機制。而在2008版本中則提出了一種全新的“沖突檢測機制”,用來解決這個問題。
這個沖突檢測機制的工作原理還是比較簡單的。在對等復制中,用來將更改應用於每個節點的存儲過程會基於每個已發布表中的某個隱藏列來檢測沖突。這個隱藏列所存儲的ID將為每個節點指定的發起方ID與行版本結合起來,實現沖突檢測。在同步期間,分發代理會針對每個表執行同步過程。這些過程會應用來自其他對等節點的插入、更新和刪除操作。如果某個過程在讀取該隱藏列的值時檢測到沖突,則數據庫就會報錯。通常情況下,如果發生這個沖突導致數據庫錯誤,數據庫分發代理會停止向這個節點應用所做的更改。
二、啟用SQL Server對等復制沖突檢測機制
通常情況下,如果多個節點服務器同時采取如下操作的話,就容易導致沖突。一是插入-插入沖突。如兩個服務器沖突向同一個表中插入數據,而每個表中所有參與對等復制的行都使用某個主鍵值來進行唯一的標識。此時在將具有相同鍵值的行插入到多個節點時,就會發生插入-插入沖突。二是更新-更新沖突。如上圖所示,服務器A與服務器B同時對某個表中相同的行進行更新,此時就會發生更新-更新沖突。與此類似,另外還可能發生插入-更細沖突、插入-刪除沖突、更新-刪除沖突、刪除-刪除沖突等等。在數據庫設計時,如果預計到會發生如上這些沖突時,則就需要考慮啟用沖突檢測機制。由於默認情況下,可以在任何節點上更改數據,因此如果不采取必要措施的話,在不同節點上進行的數據更改就會發生沖突。如果在多個節點上修改了同一行,則該行傳播給其他節點時可能會導致沖突,甚至會丟失更新的數據。有時候,這個後果會很嚴重。在數據庫設計的時候,一定要充分預計到這種情況的產生。如果企業采用的數據庫版本是2008的,則可以在各個節點上啟用沖突檢測機制,讓數據庫系統自動來檢測這種沖突,避免不需要的麻煩。在SQLServer2008的環境下,有很多種方式可以用來啟用這個沖突檢測機制。
如可以通過存儲過程來啟用和禁用各個節點的沖突檢測機制。在數據庫系統中設置了sq_addpublication存儲過程,只要管理員需要,就可以通過調用這個存儲過程來啟用某個節點的沖突檢測機制。數據庫管理員采用存儲過程來啟動或者禁止沖突檢測機制,還有一個好處。即可以指定在檢測到沖突的時候,分發代理是否應當停止應用所做的更改。默認情況下,使會讓分發代理停止應用所做的更改。筆者的建議是,如果沒有充分的必要,則不要更改這個默認值。
另外,如果數據庫管理員不希望使用命令行的方式(即通過調用存儲過程的方式)來管理這個沖突檢測機制,在還可以通過企業管理器來實現。在“發布屬性”的對話框中選擇“訂閱選項”頁簽或者通過“對等復制拓撲向導”都可以用來啟動或者禁止沖突檢測機制。不過采用這種形式來管理沖突檢測機制,跟通過存儲過程來啟用,有一個缺陷。即此時數據庫管理員會缺乏一種選擇權。因為此時分發代理在檢測到有沖突的時候自動停止應用所有的更改。而通過存儲過程來啟用沖突檢測機制時,數據庫管理員還可以選擇是應用還是放棄。在管理這個沖突檢測機制的時候,這一點差異數據庫管理員需要心中有數。然後根據自己的需要,來選擇合適的管理方式。
三、發現SQL Server對等復制沖突後的處理方式
當沖突檢測機制檢測到沖突後,該如何處理呢?筆者建議,最好按如下幾個步驟處理。
首先數據庫管理員應該配置沖突檢測警報。也就是說,無論分發代理是否應用更改,數據庫系統都應該向管理員或者用戶發出警報,告知他們產生了沖突。在SQLServer2008中,當對等復制發生沖突時,會引發對等沖突檢測警報。通常情況下,筆者都建議啟用並配置這個警報,以便管理員在發生沖突時第一時間得到相關的信息。當啟用警報功能後,如果發現有沖突,則數據庫代理將會執行已經定義的任務或者向管理員所指定的郵箱發送電子郵件或者通過發生及時消息的方式向管理員或者用戶發送警報,進行響應。同時,也可以將這些警報信息寫入到Windows應用程序日志中。
其次需要考慮沖突數據的處理方式。以上只是警報,而不會對數據產生任何實質性的影響。最終對於沖突的數據要如何處理,還是要有管理員來定。在SQLServer2008數據庫環境中,有兩種處理方式,分別為停止應用所做的更改和繼續應用所作的更改。默認情況下,數據庫推薦的是停止應用所做的更改。如上面所述,無論是通過企業管理器還是通過存儲過程來啟用沖突檢測機制,默認情況下分發代理都是會停止應用所做的更改。如果數據庫管理員覺得這麼做不合適的話,也可以通過允許分發代理繼續應用所作的更改來再次同步節點。不過這麼做的話,可能會引起一系列難以預料的問題。如此時很有可能導致數據的不一致。當出現這種情況的時候,必須在具有最高優先級的節點上手工的更新行,然後允許從該節點傳播所做的更改。更改後如果拓撲中不再有發生沖突的更改,則所有節點的數據才會保持一致。所以,不在萬不得已的情況下,不用采用這種處理方式。
四、對等復制沖突檢測機制使用的限制
雖然SQLServer2008數據庫中實現了對等復制的沖突檢測機制,不過其在配置的時候也有一些限制條件。主要的限制條件有兩個。一是對等復制中所有涉及到的可更新數據的節點都必須采用2008版本的數據庫系統。也就是說必須要先將其他的數據庫版本進行升級。二是必須要在所有的節點上都啟用這個沖突檢測機制。只要有一台沒有啟動的話,則就可能會有漏網之魚。