共用方式為


SQL 問題與解答資料庫大小、鏡像、標示的交易...等等

由 Nancy Michell 編輯

移動叢集

問:我需要將一個 SQL Server 2000 叢集移轉到新的 IP 位址,包括底下的實體伺服器以及 Windows® 叢集和 SQL Server™ 叢集。我是否需要重建整個解決方案?

答:不用,您只需要執行 SQL Server 安裝程式,並修改 IP 位址即可。本篇知識庫文件內有執行方式的說明。

資料庫大小

問:我的生產環境中採用 SQL Server 2000 SP4,其中包含:使用近 10GB 空間的關鍵資料庫、SIMPLE 復原模型、佔用 9,850MB 的主要檔案,以及 88MB 的交易記錄檔。資料庫的備份也有將近 10GB。我是否應該縮減資料庫的大小,以獲得更佳的效能?如果是,我應該使用 DBCC SHRINKDATABASE 或 DBCC SHRINKFILE?遺憾的是,我沒有非尖峰時段可執行這項維護工作。

答:DBCC SHRINKDATABASE 或 DBCC SHRINKFILE 只有在資料庫歷經多次刪除和更新之後會縮小資料量時,才會有所助益。我好奇的是,您為什麼要考慮這個問題呢?現在每 10 GB 的磁碟空間價格大約只要 $20 美金。再增添 100GB 左右的磁碟空間讓系統運用,不是更理想嗎?空間愈分為片段,效能就愈趨下降,但如果您無法進行維護,就沒有太多選擇。有的人在這種情況下會使用資料庫的第二份複本。他們會透過複寫的方式保持一份最新的備份,然後針對備份複本進行維護,最後再將應用程式切換到備份上執行。這顯然需要變更一些程式碼,並且無法使用 SIMPLE 復原模型 (需要改為 FULL 或 BULK_LOGGED),不過就長遠來看,可能是不錯的解決方案。

升級與效能

問:我需要將兩個應用程式從 SQL Server 2000 移轉到 SQL Server 2005。我該如何避免在升級過程中影響效能?

答:一般而言,下列情形都可能在升級時導致效能降低,因此請盡量避免:

  1. 您在升級至 SQL Server 2005 之後,尚未重建統計資料。
  2. 您有 JOINS 和 WHERE 子句,其中會比較兩種不同的資料型別,因而導致效能不良,這尤其在伺服器原來執行的是 SQL Server 2000 SP3 (含) 以前的版本 (請參閱 support.microsoft.com/kb/271566/)。
  3. SQL Server 2005 執行個體的組態有誤;記憶體、Address Windowing Extensions (AWE)、驅動程式...等等的組態不正確。執行 SQL Server 2000 的電腦已經過調整,但是執行者已離職且沒有記載相關的變更,因此從未在 SQL Server 2005 執行個體中完成相對的調整。
  4. 硬體出問題。購買新硬體的原因,通常是要讓宣傳單看起來更耀眼,但實際使用上卻不如預期。

讓 SQL Server 執行個體進入生產階段之前,必須先建立效能基準線,才能確定您所預期的效能可以實現。這樣就能排除基礎結構方面的問題。您必須查看 Perfmon 計數器,例如磁碟、I/O 及記憶體,並且和執行個體之間進行比較。

資料庫鏡像

問:我有使用資料庫鏡像,而想要啟用 READ_COMMITTED_SNAPSHOT 資料庫選項。我在鏡像設定完成之後嘗試啟用該選項時,出現了例外狀況,其中表示 db 正處於鏡像工作階段所以無法執行命令。

答:這是由於設定 READ_COMMITTED_SNAPSHOT 選項之後需要重新啟動資料庫,才能生效。因此,您必須中斷鏡像階段、設定選項,然後重新啟動資料庫。這些步驟完成之後,您就可以重新建立鏡像。鏡像資料庫在建立工作階段之後會偵測到設定的選項,並於萬一需要容錯移轉時套用。

問:我嘗試安裝同步鏡像,卻得到 1418 錯誤。執行 Netstat -ano 顯示 SQL Server 正在所有伺服器的正確埠上接聽。但是在我嘗試啟動鏡像時,卻出現錯誤訊息。到底是怎麼回事呢?

答:其中一個可能性,是您的防火牆封鎖了通訊管道;這是相當常見的問題,您應該進一步檢查探討。請參閱下列白皮書的詳細說明:Troubleshooting Database Mirroring Setup (英文) 以及 MSSQLSERVER_1418 (英文)。

只要記住,這個問題並非僅針對非同步鏡像。事實上也有可能發生在同步鏡像。

您看到的錯誤訊息 (「伺服器網路位址 "%.*ls" 無法連上或不存在。請檢查網路位址名稱,然後重新發出命令」) 是正確的。通常並非遠端夥伴不存在,只是找不到遠端夥伴而已。

如果遠端夥伴已關閉、未接聽該埠,甚至於結束點已關閉 (可能由於夥伴無法以相同的加密機制進行交涉,或者有其他的驗證問題),就有可能發生這樣的狀況。此外,亦有可能是夥伴遭到封鎖,這可能是由發出命令之夥伴的防火牆所導致。

可能需要排除的其他問題,包括資料來源名稱 (DSN) 以及名稱解析問題。一般建議使用完整的網域名稱。總之,雖然問題經常是防火牆造成的,但還是要記住有許多其他潛在原因。

問:我想使用 SQL Server 2005 鏡像功能;不過我聽說在多重應用程式連接到同一 SQL Server 執行個體的多個資料庫時,不建議使用鏡像。這是正確的嗎?

答:其實要看每個應用程式究竟使用自己的資料庫、跨資料庫,又或者是以分散式交易協調器 (Distributed Transaction Coordinator,DTC) 交易而定。如果使用跨資料庫交易,那麼鏡像可能造成邏輯上的不一致,而無法以預期的方式認可交易。有關這類情況所導致的結果以及詳細說明,請參考此文件 (英文)。

如果多重應用程式使用多個資料庫,而每個應用程式都有自己的資料庫,那麼鏡像就不會造成這些問題。

標示的交易

問:「標示的交易」究竟是什麼?若一個資料庫是 SQL Server,另一個是 Oracle,這樣是否還能使用標示的交易?

答:交易的標示是 DBA 定期的工作,就是在所有記錄的相同位置放入標記。這項動作只要結合還原資料表至交易標記的能力,即可讓您將所有資料庫還原至同一時間點。這樣的作法十分痛苦,因為您必須還原所有相關資料庫,而所有資料庫中的資料都會遺失,因此您必須確保自己別弄丟記錄檔,才能避免這種情況發生。標示的交易是 SQL Server 專屬的功能,因此若是您的分散式交易中包括 SQL Server 以外的其他資料庫,這些資料庫就無法加入交易標記。一般而言,只有極少數的分散式資料庫系統使用交易標記。他們只會把交易記錄的遺失視為災難事件,需要大量手動作業才能復原。

Access-To-T-SQL 轉換工具

問:針對預存程序,是否有現成的自動化轉換工具可將 Access™-SQL 轉換到 T-SQL?

答:請嘗試 SQL Server Migration Assistant (SSMA) for Access,您可以從此處下載 (英文)。其中還有 SQL Server Migration Assistant for Oracle、SQL Server Migration Assistant for Sybase 以及 Migrating Informix Databases to Microsoft® SQL Server 2000。

若要從 Access 升級至 SQL Server,您可使用 Office Upsizing Wizard,不過 [圖 1] 所顯示的 SSMA for Access 有更多功能,包括轉換評定報告以及網路掃描。SSMA for Access 亦可修正許多目前 Office Upsizing Wizard 無法正確處理的問題。

圖 1 SQL Server Migration Assistant for Access

圖 1** SQL Server Migration Assistant for Access **(按影像可放大)

非叢集索引

問:我有一個資料表,其中的主索引鍵是由兩個 GUID 組成 (假設為 GUID1 和 GUID2)。我已經針對 GUID1 和 GUID2 建立唯一的叢集索引。現在為了要提升效能,我想在 GUID2 及 GUID1 上建立第二個非叢集索引。請問如果我宣告索引是唯一的,是否會降低效能?

答:宣告非叢集索引是唯一的,對效能並不會有負面的影響。事實上,這樣做會減少索引樹狀結構的層級。

非叢集索引宣告為非唯一時,資料列定位器會附加至根頁面和非分葉頁面中、索引項目的索引鍵部分。如此一來,就能方便刪除和更新索引項目,以避免出現重複的索引鍵項目時掃描同義字鏈結 -- 而是可藉由索引鍵加上定位器的系統搜尋作業,找出要變更的特定項目。結果是這些項目的長度會增加 (就您所選擇的叢集索引鍵而言會相當長)。因此,根頁面和非分葉頁面自然會更快速的填滿。如果索引是唯一的,就應該用這樣的方式宣告之。

重點是,不論資料表是否有叢集索引,任何資料表上未宣告為唯一的非叢集索引,都會將定位器附加至根頁面和其他非分葉頁面的索引項目上。

此外,如果您使用 int 識別項資料行做為代理 (Surrogate) 索引鍵,然後加上兩個唯一的索引鍵 (GUID1,GUID2) 以及 (GUID2,GUID1),這樣就十分有機會能夠改善效能,因為索引中會有 4 位元組的叢集索引鍵,而不是 32 位元組的叢集索引鍵。

更新鎖定

問:我的預存程序結構如下:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION

-- Get The lock if available
UPDATE    ProcessingInstances 
SET       LockHolder = @MessageId
WHERE     ( InstanceId = @InstanceId ) 
AND       ( LockHolder IS NULL )

COMMIT TRANSACTION

此預存程序只允許一位呼叫者取得鎖定,其他呼叫者必須等待。請問我是否能藉由減少隔離等級,達到相同的目的?

READ COMMITTED 似乎才是正確的隔離等級,因為此交易只有一項查詢,而且如果有其他交易也在更新相同的記錄,此交易就必須等待其他交易完成。這是正確的嗎?

答:造成其他呼叫者等待的並不是範例中的可序列化設定,而是更新作業本身。沒錯,您可以將隔離等級設定為 READ COMMITTED,這樣更新作業就會在其使用的索引上採用更新鎖定。這會導致其他程序在執行相同陳述式時發生問題,因此他們會進行封鎖,直到更新完成 (如果更新是唯一的陳述式,那麼您也不需要明確交易;每個陳述式若不屬於外顯,則都會隱含在自己的交易中)。

然而,若 UPDATE 陳述式中的 WHERE 子句沒有找到符合的資料列,則使用可序列化的隔離等級,就會導致這類資料列無法於其他交易中進行插入或修改。如果您以 READ COMMITTED 隔離等級執行 UPDATE,就不會發生上述情況,且其他交易就可以引入符合更新的資料列。倘若預存程序碼和您提供的程式碼相同,則採取上述任一 (可序列化或交易) 動作都沒有意義;只要直接執行更新即可。

感謝下列 Microsoft IT 專家提供其技術專業知識: Gaurav Aggarwal、Anthony Bloesch、Todd Briley、Shaun Cox、Roberto Di Pietro、Michael Epprecht、Kevin Farlee、Umachandar Jayachandran、Chuck Ladd、Kaloian Manassiev、Luciano Moreira、Ward Pond、Mark Prazak、Arunachalam Thirupathi、Roger Wolter、Clement Yip 及 Frankie Yuen。

© 2008 Microsoft Corporation and CMP Media, LLC. 保留所有權利;未經允許,嚴禁部分或全部複製.