SQL Server 高可用鏡像實(shí)現(xiàn)原理
數(shù)據(jù)副本
鏡像技術(shù)實(shí)現(xiàn)了位于不同物理服務(wù)器上的兩個(gè) SQL Server 實(shí)例數(shù)據(jù)同步,在鏡像集群中, SQL Server 實(shí)例具有三種角色:
○ Principal:具有完整的數(shù)據(jù)副本,對(duì)外提供數(shù)據(jù)庫(kù)讀寫服務(wù);
○ Mirror:具有完整的數(shù)據(jù)副本,本身不提供讀寫服務(wù),通過接收來自 Principal 的更新日志實(shí)現(xiàn)數(shù)據(jù)同步,允許創(chuàng)建快照實(shí)現(xiàn)報(bào)表;
○ Witness:本身不存儲(chǔ)數(shù)據(jù),只負(fù)責(zé)在高安全運(yùn)行模式下提供自動(dòng)故障切換的能力,確保兩個(gè) SQL Server 實(shí)例只有一個(gè)對(duì)外提供服務(wù),避免腦裂情況出現(xiàn);
在鏡像集群中,principal 和 mirror 的數(shù)據(jù)同步是依靠事務(wù)日志來實(shí)現(xiàn)的,與 Oracle 和 MySQL 不同,SQL Server 的事務(wù)日志是 Database 級(jí)別的,不是實(shí)例級(jí)別的,每個(gè) Database 都單獨(dú)的事務(wù)日志,這也就使得 SQL Server 的鏡像是可以基于 Database 層面實(shí)現(xiàn)。
一個(gè) SQL Server 實(shí)例中的兩個(gè) Database,一個(gè)可以作為 principal,一個(gè)可以作為 mirror,分別與其他 SQL Server 實(shí)例組建鏡像關(guān)系;另外,SQL Server 一個(gè) Database 只能有一個(gè) mirror 節(jié)點(diǎn),一個(gè) mirror 的 database 不可以再有 mirror 節(jié)點(diǎn),這點(diǎn)與 MySQL 級(jí)聯(lián)復(fù)制不同;
SQL Server 的事務(wù)日志是物理記錄級(jí)別的,記錄了對(duì)數(shù)據(jù)庫(kù)某個(gè)頁的某行記錄(slot)的操作,principal 創(chuàng)建鏡像后,會(huì)啟動(dòng)一個(gè)單獨(dú)的事務(wù)日志發(fā)送線程,維護(hù)一個(gè)虛擬的發(fā)送隊(duì)列,然后讀取事務(wù)日志,將其進(jìn)行壓縮,根據(jù)官方公布的測(cè)試數(shù)據(jù),壓縮比不低于12.5%,然后發(fā)送給 mirror 節(jié)點(diǎn),mirror 節(jié)點(diǎn)接收到以后,會(huì)將其寫入本地在磁盤上的一個(gè)重做隊(duì)列文件中,然后再通過另外的一個(gè)線程異步的方式,從重做隊(duì)列中獲取事務(wù)日志,然后分發(fā)給應(yīng)用線程(process unit)進(jìn)行回放。
不同于 MySQL Binlog,由于 SQL Server 的事務(wù)日志在 principal 上事務(wù)執(zhí)行過程中就已經(jīng)源源不斷的寫入(MySQL Binlog 僅在事務(wù)提交階段生成),在 principal 事務(wù)執(zhí)行的同時(shí)事務(wù)日志就已經(jīng)傳遞給了 mirror,所以基于事務(wù)日志的 SQL Server 的復(fù)制性能會(huì)更理想。同時(shí),在 mirror 回放的過程中,可以基于頁(page)級(jí)別進(jìn)行并發(fā)更新(redo parallel),在 SQL Server 的標(biāo)準(zhǔn)版中,僅提供一個(gè)線程進(jìn)行事務(wù)日志回放(roll forward),在企業(yè)版中,如果當(dāng)前服務(wù)器 CPU 大于5核,則每4個(gè)核,增加一個(gè)并行線程,如果低于5個(gè)核,則仍然使用單線程回放。同時(shí),基于頁的事務(wù)日志的并發(fā)執(zhí)行,還有一個(gè)好處就是對(duì)于同一個(gè)頁面的更新可以合并刷新,減少臟頁刷新數(shù)量。