


Windows存儲(chǔ):SQL行溢出、差異備份及疑問(wèn)
問(wèn):我最近升級(jí)了一個(gè)應(yīng)用程序,使其可以在 SQL Server 2005 上運(yùn)行。我利用了允許行長(zhǎng)度超出 8,060 個(gè)字節(jié)這項(xiàng)功能,以便用戶可以創(chuàng)建較長(zhǎng)的數(shù)據(jù)字段而不會(huì)收到從 SQL Server 返回的錯(cuò)誤。現(xiàn)在,將這個(gè)應(yīng)用程序應(yīng)用到實(shí)際環(huán)境之后,一些掃描查詢開始出現(xiàn)性能問(wèn)題,在架構(gòu)更改之前,這些查詢運(yùn)行正常。我也檢查過(guò)各種索引的碎片,一切正常。那為什么查詢?cè)?SQL Server 2005 上運(yùn)行時(shí)速度比較慢呢?
答:您所利用的“行溢出”功能,對(duì)于在特定情況下允許行長(zhǎng)度大于 8,060 個(gè)字節(jié)效果很好,但卻不適合大多數(shù)長(zhǎng)度過(guò)大的行,而且可能使查詢性能大打折扣,正如您所遇到的情況那樣。
發(fā)生這種情況的原因是,當(dāng)某行的長(zhǎng)度開始變得過(guò)大時(shí),該行中的其中一個(gè)可變長(zhǎng)度列會(huì)被“推出行”。這意味著該列會(huì)在數(shù)據(jù)或索引頁(yè)上從行中移到文本頁(yè)中。至于原來(lái)列中的值,會(huì)由指針取代,指向該列中的值在數(shù)據(jù)文件中的新位置。
這與用來(lái)存儲(chǔ) XML、文本、圖像或 varchar(max) 等常規(guī) LOB(大型對(duì)象)列的機(jī)制完全相同。請(qǐng)注意,如果表架構(gòu)包含多個(gè)可變長(zhǎng)度列,就無(wú)法保證在多個(gè)行的長(zhǎng)度變得過(guò)大時(shí)推出的會(huì)是同一列。
這種機(jī)制可能會(huì)產(chǎn)生性能問(wèn)題。如果查詢從一個(gè)表格行中檢索的可變長(zhǎng)度列已被推出該行,可能突然之間需要額外的 I/O 來(lái)讀取內(nèi)含行外位置的值的文本頁(yè)。如果有多個(gè)行的長(zhǎng)度過(guò)大,從多個(gè)行中檢索相同的可變長(zhǎng)度列的查詢,可能產(chǎn)生無(wú)法預(yù)料的性能問(wèn)題,嚴(yán)重程度取決于被推出行的值的數(shù)量。
在您遇到的情況中,對(duì)包含可變長(zhǎng)度列的選擇列表執(zhí)行范圍掃描或表掃描的查詢,正是因行溢出及其影響而導(dǎo)致性能下降。這與索引是否執(zhí)行過(guò)完全的碎片整理無(wú)關(guān),當(dāng)可變長(zhǎng)度列被推出行時(shí),因?yàn)楸仨毷褂秒S機(jī) I/O 讀取內(nèi)含行外的值的文本頁(yè),所以之前有效的掃描作業(yè)已基本中斷。
雖然行溢出在特定的情況下對(duì)于長(zhǎng)度過(guò)大的行仍然很有用,但如果查詢的性能至關(guān)重要,則不應(yīng)該在您的設(shè)計(jì)里面過(guò)度利用。
問(wèn):我們剛在兩個(gè)故障轉(zhuǎn)移群集之間引入了數(shù)據(jù)庫(kù)鏡像,作為以低于存儲(chǔ)區(qū)域網(wǎng)絡(luò) (SAN) 復(fù)制的成本獲得地理冗余的方法。因?yàn)閿?shù)據(jù)中心位于同一個(gè)城市,所以我們能夠使用同步鏡像。問(wèn)題在于當(dāng)本地群集上發(fā)生故障轉(zhuǎn)移時(shí),鏡像數(shù)據(jù)庫(kù)會(huì)故障轉(zhuǎn)移到遠(yuǎn)程群集,而這并不是我們希望發(fā)生的情況。我們?cè)撊绾伪苊獬霈F(xiàn)這種情況?我們只希望在本地群集無(wú)法使用的時(shí)才進(jìn)行故障轉(zhuǎn)移。
答:為了提高可用性,鏡像會(huì)安裝一個(gè)見證服務(wù)器,以便在主體服務(wù)器無(wú)法使用時(shí)自動(dòng)發(fā)生故障轉(zhuǎn)移。其理論基礎(chǔ)是:如果整個(gè)本地群集出現(xiàn)故障,數(shù)據(jù)庫(kù)鏡像將故障轉(zhuǎn)移到第二個(gè)群集,這樣應(yīng)用程序就可以繼續(xù)執(zhí)行了。
此問(wèn)題出現(xiàn)在群集故障轉(zhuǎn)移期間。故障轉(zhuǎn)移所花的時(shí)間超過(guò)了數(shù)據(jù)庫(kù)鏡像的默認(rèn)超時(shí)設(shè)置,而見證服務(wù)器和鏡像服務(wù)器(即第二個(gè)群集上活動(dòng)的 SQL Server 實(shí)例)均認(rèn)為它們看不到主體服務(wù)器,于是鏡像服務(wù)器便開始將鏡像故障轉(zhuǎn)移到第二個(gè)群集。
預(yù)防這種現(xiàn)象最簡(jiǎn)單的方法是刪除見證服務(wù)器,以便數(shù)據(jù)庫(kù)鏡像在本地群集出現(xiàn)故障時(shí)不會(huì)自動(dòng)進(jìn)行故障轉(zhuǎn)移。當(dāng)然,這種做法會(huì)降低可用性,因?yàn)檫@樣一來(lái)就需要人為啟動(dòng)故障轉(zhuǎn)移。
第二種方法是更改數(shù)據(jù)庫(kù)鏡像的默認(rèn)超時(shí)設(shè)置,也就是更改確定主體服務(wù)器不可用之前,它響應(yīng)“ping”信息(每秒一次)失敗的次數(shù)。這種設(shè)置稱為“伙伴超時(shí)”(Parnter Timeout),默認(rèn)值為 10。可使用下列代碼找到數(shù)據(jù)庫(kù)當(dāng)前的超時(shí)值:
SELECT mirroring_connection_timeout FROM master.sys.database_mirroring WHERE database_id = DB_ID ('mydbname'); GO |
可使用下列代碼更改超時(shí)值:
ALTER DATABASE mydbname SET PARTNER TIMEOUT <timeoutvalue>; GO |
對(duì)于這種情況,設(shè)置的伙伴超時(shí)值必須大于在本地群集上進(jìn)行群集故障轉(zhuǎn)移的常規(guī)時(shí)間值。在鏡像數(shù)據(jù)庫(kù)上進(jìn)行群集故障轉(zhuǎn)移時(shí)確定運(yùn)行恢復(fù)所需的時(shí)間變化,可能有些困難,不過(guò)您應(yīng)該可以判斷出上限。這種方法的缺點(diǎn)在于超時(shí)值可能必須以分鐘為單位,不適合在發(fā)生真正的災(zāi)難時(shí)使用。
問(wèn):我使用的備份策略包括完整備份和日志備份,但有人建議我應(yīng)該加入差異備份來(lái)縮短還原時(shí)間。我每周進(jìn)行一次完整備份,每個(gè)小時(shí)進(jìn)行一次日志備份。我試過(guò)每天添加差異備份,但我注意到一個(gè)異常現(xiàn)象:每個(gè)星期結(jié)束時(shí)的差異備份與每周的完整備份大小差不多。我記得差異備份與日志備份一樣都屬于增量備份啊!難道是我記錯(cuò)了嗎?
答:這是對(duì)差異備份的本質(zhì)有所誤解造成的。差異備份與日志備份不同,不屬于增量備份。差異備份包含自上次完整備份后所有更改的數(shù)據(jù)文件范圍(這適用于數(shù)據(jù)庫(kù)、文件組和文件級(jí)別備份)。
如果范圍(包含八個(gè)連續(xù)數(shù)據(jù)文件頁(yè)的邏輯組)有任何更改,都會(huì)標(biāo)記在稱為差異圖的特殊位圖頁(yè)中。每個(gè)數(shù)據(jù)文件的每 4GB 就有一個(gè)差異圖。進(jìn)行差異備份時(shí),備份子系統(tǒng)會(huì)掃描所有差異圖,并復(fù)制所有已更改的范圍,但不會(huì)重置差異圖。這表示連續(xù)的差異備份之間更改的范圍越大,后者的備份會(huì)越大。只有在執(zhí)行完整備份時(shí)才會(huì)重置差異圖。
如果應(yīng)用程序工作負(fù)載太大,以至于數(shù)據(jù)庫(kù)內(nèi)容在短時(shí)間(假設(shè)在一個(gè)星期)內(nèi)進(jìn)行了大量更改,那么每周的完整備份大小幾乎會(huì)與在下一個(gè)完整備份前進(jìn)行的差異備份的大小相同。這也解釋了您看到的現(xiàn)象。
另外,差異備份確實(shí)提供了一種在災(zāi)難恢復(fù)的情況下縮短還原時(shí)間的方法。如果您采用的備份策略是每周進(jìn)行一次完整備份,每小時(shí)進(jìn)行一次日志備份,那么您必須執(zhí)行下列操作才能最迅速地實(shí)現(xiàn)還原:
運(yùn)行尾日志備份(自最近的日志備份后生成的所有日志)。
還原最近的完整數(shù)據(jù)庫(kù)備份。
按順序還原自最近的完整數(shù)據(jù)庫(kù)備份后的所有日志備份。
還原尾日志備份。
這可能需要還原大量日志備份,尤其是在災(zāi)難剛好發(fā)生在進(jìn)行下次完整備份之前。(最糟的情況是需要還原 24 + 24 + 24 + 24 + 24 + 24 + 23 個(gè)日志備份!)在此策略中每天添加差異備份,還原的順序會(huì)變成這樣:
運(yùn)行尾日志備份(自最近的日志備份后生成的所有日志)。
還原最近的完整數(shù)據(jù)庫(kù)備份。
還原最近的差異備份。
按順序還原自最近的差異備份后的所有日志備份。
還原尾日志備份。
這樣就不必還原大量的日志備份了,因?yàn)檫原差異備份與還原差異備份涵蓋期間內(nèi)的所有日志備份基本相同。
在每天執(zhí)行差異備份的情況下,即使是在該周的最后一天,最糟的情況也不過(guò)是 23 個(gè)日志備份。差異備份不屬于增量備份,它的一個(gè)缺點(diǎn)是它們可能會(huì)占用更多的空間,但與縮短還原時(shí)間相比,這是值得的。
問(wèn):我有一個(gè)兩節(jié)點(diǎn)的故障轉(zhuǎn)移群集,每個(gè)節(jié)點(diǎn)都運(yùn)行一個(gè) SQL Server 2005 實(shí)例。我按照通常的要求,將每個(gè)實(shí)例設(shè)置為只使用 50% 的可用內(nèi)存。現(xiàn)在我遇到了一些問(wèn)題,因?yàn)閮蓚(gè)實(shí)例上的工作負(fù)載都需要更多的內(nèi)存才能維持相同的性能級(jí)別。如果我刪除內(nèi)存限制,或是增加內(nèi)存,我想我會(huì)碰到這樣的問(wèn)題:其中一個(gè)實(shí)例故障轉(zhuǎn)移,然后兩個(gè)實(shí)例都只在一個(gè)節(jié)點(diǎn)上運(yùn)行。您有什么建議?
答:我會(huì)針對(duì)兩節(jié)點(diǎn)、雙實(shí)例的情況來(lái)解答這個(gè)問(wèn)題,但下列內(nèi)容也適用于其他多實(shí)例設(shè)置(N-1 故障轉(zhuǎn)移群集,其中有 N 個(gè)節(jié)點(diǎn)和 N-1 個(gè) SQL Server 實(shí)例)。
許多人在兩個(gè)實(shí)例上都遇到過(guò)高工作負(fù)載的情況(占用的服務(wù)器內(nèi)存超過(guò) 50%),而沒(méi)有考慮到兩個(gè)實(shí)例在發(fā)生故障轉(zhuǎn)移后最后會(huì)在一個(gè)節(jié)點(diǎn)上運(yùn)行對(duì)工作負(fù)載的影響。如果沒(méi)有特殊的配置,實(shí)例之間的內(nèi)存分配很可能會(huì)不成比例,結(jié)果一個(gè)工作負(fù)載正常運(yùn)行,而另一個(gè)卻慢得不行。
對(duì)于 SQL Server 2000,建議將每個(gè)實(shí)例限制為最多使用 50% 的群集節(jié)點(diǎn)內(nèi)存。這是因?yàn)?SQL Server 2000 中的內(nèi)存管理器并不會(huì)對(duì)內(nèi)存不足做出響應(yīng) — 假如 SQL Server 占用了節(jié)點(diǎn) 80% 的內(nèi)存,它并不會(huì)降低內(nèi)存使用量。這表示在故障轉(zhuǎn)移的情況下,另一個(gè)剛啟動(dòng)的實(shí)例只有 20% 的內(nèi)存可用。通過(guò)將兩個(gè)實(shí)例限制為最多使用節(jié)點(diǎn) 50% 的內(nèi)存,可保證每個(gè)故障轉(zhuǎn)移實(shí)例有 50% 的內(nèi)存。不過(guò),這種方法產(chǎn)生的問(wèn)題是每個(gè)實(shí)例上的工作負(fù)載也會(huì)限制為使用 50% 的內(nèi)存。
而對(duì)于 SQL Server 2005(和 SQL Server 2008),內(nèi)存管理器可以響應(yīng)內(nèi)存不足,因此 50% 的上限不再適用。但是沒(méi)有這類限制,如果兩個(gè)實(shí)例都在一個(gè)群集節(jié)點(diǎn)上運(yùn)行,它們可能會(huì)爭(zhēng)用內(nèi)存直到產(chǎn)生不成比例的內(nèi)存分配。
答案是將每個(gè)實(shí)例設(shè)置為最低內(nèi)存量,這樣一來(lái),它們就不會(huì)被迫釋放過(guò)多的內(nèi)存。對(duì)于兩節(jié)點(diǎn)、雙實(shí)例的情況,最常見的設(shè)置是為每個(gè)實(shí)例至少配置 40% 的內(nèi)存。這表示當(dāng)每個(gè)實(shí)例在不同的節(jié)點(diǎn)上運(yùn)行時(shí),它們可以占用任意內(nèi)存量。而當(dāng)發(fā)生故障轉(zhuǎn)移時(shí),會(huì)保證每個(gè)實(shí)例有特定的內(nèi)存量,以保持固定的工作負(fù)載性能級(jí)別,并留一些內(nèi)存在兩者之間共享。雖然這意味著兩個(gè)工作負(fù)載的性能在發(fā)生故障轉(zhuǎn)移時(shí)可能會(huì)下降(在意料之中),但是每個(gè)實(shí)例在不同的群集節(jié)點(diǎn)上運(yùn)行的大多數(shù)時(shí)間完全不會(huì)受到限制。
關(guān)鍵字:SQL Server、服務(wù)器、集群
新文章:
- CentOS7下圖形配置網(wǎng)絡(luò)的方法
- CentOS 7如何添加刪除用戶
- 如何解決centos7雙系統(tǒng)后丟失windows啟動(dòng)項(xiàng)
- CentOS單網(wǎng)卡如何批量添加不同IP段
- CentOS下iconv命令的介紹
- Centos7 SSH密鑰登陸及密碼密鑰雙重驗(yàn)證詳解
- CentOS 7.1添加刪除用戶的方法
- CentOS查找/掃描局域網(wǎng)打印機(jī)IP講解
- CentOS7使用hostapd實(shí)現(xiàn)無(wú)AP模式的詳解
- su命令不能切換root的解決方法
- 解決VMware下CentOS7網(wǎng)絡(luò)重啟出錯(cuò)
- 解決Centos7雙系統(tǒng)后丟失windows啟動(dòng)項(xiàng)
- CentOS下如何避免文件覆蓋
- CentOS7和CentOS6系統(tǒng)有什么不同呢
- Centos 6.6默認(rèn)iptable規(guī)則詳解