Hi-Fi優質I.T網:技術文章...
您尚未登入...
帳號:
密碼:

忘記密碼 
 
  訂閱電子報

取消   訂閱
 
2004/9/5-2:7:39
 SQL Server 連線基本概念│作者:Ken Henderson│分數:1

 

摘要:SQL Server 2000 用戶端使用 API、物件程式庫和通訊協定的堆疊連線到 SQL Server。Ken Henderson 介紹每一個元件並說明它們運作及交互操作的方式。

簡介

在堆疊的頂層是 API 或物件程式庫。應用程式是經由物件程式庫所公開的 API 功能或介面連線到 Microsoft®SQL Server。用於存取 SQL Server 的 API 範例包括 ODBC 和 DB 程式庫。用於存取 SQL Server 的物件程式庫範例包括 OLE DB、ADO 和 ADO.NET。因為 ADO 最終還是使用 OLE DB 來和伺服器通訊,因此 Windows 應用程式常用於和 SQL Server 通訊的物件程式庫實際上只有兩種:OLE DB 和 ADO.NET。經由 ADO 或 ADO.NET 連線當然比在 ODBC 上更普遍 (雖然 SQL Server 的 Query Analyzer 和 Enterprise Manager 仍是在 ODBC 上連線),所以我會根據 ADO/OLE DB 和 ADO.NET 來討論 SQL Server 連線架構的用戶端。現今大多數的應用程式是使用物件程式庫連線到 SQL Server,而非使用 ODBC 或其他類似的元件。

ADO 和 OLE DB

OLE DB 用戶端 (也稱為取用者) 是經由用戶端提供者的方式與伺服器及其他後端通訊。這個提供者是一或多組 COM 元件,用於將應用程式的要求轉譯成網路處理序之間的通訊 (IPC) 要求。在 SQL Server 的例子中,最常用的 OLE DB 提供者是 SQLOLEDB,也就是 Microsoft 為 SQL Server 所提供的 OLE DB 提供者。SQLOLEDB 隨附於 SQL Server 並安裝為 Microsoft Data Access Components (MDAC) 堆疊的一部分。

使用 ADO 與 SQL Server 通訊的應用程式首先會使用 Connection 物件與伺服器建立連線來達成。ADO 的 Connection 物件會接受一個指定 OLE DB 提供者的連接字串作為傳入的參數。如果應用程式是使用 SQLOLEDB 提供者連線到 SQL Server,您會在此字串中看到「SQLOLEDB」。

ADO 應用程式也有可能在 ODBC 上連線到 SQL Server。若要這麼做的話,應用程式要使用 ODBC 的 OLE DB 提供者並在其連接字串中指定參照到目標 SQL Server 的 ODBC 資料來源。在這個案例中,應用程式和 OLE DB 通訊,然後 ODBC 的 OLE DB 提供者使得適當的 ODBC API 呼叫和 SQL Server 進行交談。

ADO.NET

ADO.NET 應用程式通常會使用 .NET Framework Data Provider for SQL Server 連線到 SQL Server。此原始提供者允許 ADO.NET 物件直接與 SQL Server 進行通訊。通常,應用程式會使用 SqlConnection 物件來建立連線,然後使用 SqlCommand 物件傳送命令到伺服器並接收回應的結果。SqlDataAdapter 和 SqlDataReader 類別通常是用來和 SqlCommand 結合,以便與 Managed 程式碼應用程式的 SQL Server 進行互動。

透過利用 OleDbConnection 類別,ADO.NET 應用程式也可以使用 SQLOLEDB OLE DB 提供者與 SQL Server 進行互動。而且它們可以經由 OdbcConnection 類別使用 ODBC 來存取 SQL Server。所以,僅單獨從 Managed 程式碼,您就有三種不同的方法從應用程式來存取 SQL Server。以疑難排解的觀點來看這是件好事,因為它可將您所遭遇到有關連線的問題分離到特定資料存取層級或程式庫。

用戶端網路程式庫

在堆疊中的下一層是網路程式庫。網路程式庫在應用程式用於和 SQL Server 通訊的 API 或物件程式庫,以及用於和網路交換資料的網路通訊協定之間提供著導管的作用。SQL Server 提供網路程式庫所有主要的網路通訊協定。這些程式庫可以無障礙地處理從用戶端傳送要求到 SQL Server,以及將伺服器的回應傳回給用戶端。您可以使用 SQL Server 的用戶端網路公用程式,來設定特定用戶端上提供哪些網路程式庫。支援的用戶端通訊協定包括 TCP/IP、Named Pipes、NWLink、Multiprotocol (RPC) 和其他。

在此特別值得一提的網路程式庫是共用記憶體網路程式庫。正如其名,這個網路程式庫使用 Windows 的共用記憶體功能在 SQL Server 用戶端和伺服器之間進行通訊。當然,這意味著用戶端和伺服器必須存放在相同的實體機器上。

因為能夠略過實體網路堆疊,共用記憶體網路程式庫比其他的網路程式庫快相當地多。同步物件會保護對共用記憶體區域的存取,所以在用戶端和伺服器之間通訊的速度主要受限於,Windows 對核心物件發出和解除信號的能力以及複製資料進出共用記憶體區域的處理能力。

在連線時,您可以指定期間或將 (local) 用作為電腦名稱,以指出要使用共用記憶體網路程式庫。當連線時,您也可以在機器\執行個體名稱加上前置詞 lpc:,以指出您要使用共用記憶體網路程式庫。

請瞭解,即使是連線到在相同機器上的 SQL Server,共用記憶體網路程式庫並不必然是您最佳的連線選項。在某些情況下,用戶端和伺服器之間的連線太過直接會限制其延展性。如同在應用程式整體架構中的其他元素,在假設某個技術解決方案比替代方法有較佳的擴充性或速度較快之前應先進行徹底的測試。

連線

當用戶端連線時,SQL Server 的使用者模式排程器 (UMS) 元件會將之指定給一個特定的排程器。在啟動時,SQL Server 會為系統上的每個 CPU 建立不同的 UMS 排程器。當用戶端連線到伺服器時,會以最少的連線數量將之指定給排程器。一旦建好連線,用戶端就不會再變更排程器 — 它會保持在指定的排程器上直到中斷連線。

對於建立多重連線到伺服器的應用程式而言,這有著重要的含意。如果應用程式設計不良或者沒有將工作平均分配在各個連線上,有可能會導致應用程式的部份連線間,在某些連線幾乎是處於閒置狀態的情況下,卻不必要地爭用 CPU 資源。

例如,應用程式建立四個連線到裝配有雙處理器且執行 SQL Server 的機器上,連線 1 和 3 連接到處理器 0 上,而連線 2 和 4 連接到處理器 1 上。如果應用程式工作最多的部份是由連線 1 和 3 來執行的,則它們可能在 CPU 1 仍保持幾乎閒置的時候爭用 CPU 0。在這種情況下,應用程式無能為力,只有中斷連線 / 重新連線並希望連線 1 和 3 能連接到不同的 CPU 上 (在連線時無法指定 CPU 的傾向) 或者重新分配工作量到各個連線以使它們為平均。當然,後者遠比前者好。

連線記憶體

SQL Server 為用戶端的每個連線保留三個封包的緩衝區。每一個緩衝區的大小是視 sp_configure 預存程序所指定之預設網路封包的大小而定。如果預設網路封包大小小於 8KB,則這些封包的記憶體是來自 SQL Server 的緩衝集區。如果它等於或大於 8KB,則會從 SQL Server 的 MemToLeave 區域來配置記憶體。

值得注意的是,.NET Framework Data Provider for SQL Server 的預設網路封包大小是 8KB,所以與 Managed 程式碼用戶端連線相關聯的緩衝區通常來自 SQL Server 的 MemToLeave 區域。和傳統的 ADO 應用程式相對照,ADO 應用程式的預設封包大小是 4KB,且緩衝區是配置於 SQL Server 緩衝集區。

事件

一旦建立連線,用戶端的要求通常歸為兩大類:語言事件和遠端程序呼叫。雖然確有其他的類型,但大部分 SQL Server 用戶端對伺服器的要求是由這兩種類型之一所構成的。語言事件是從用戶端傳送給伺服器的 T-SQL 批次。例如,如果您呼叫 ADO Command 物件的 Execute 方法,該物件的 CommandText 屬性會設定為 T-SQL 查詢,且 CommandType 屬性會設定為 adCmdText,則會將查詢以語言事件提交給伺服器。同樣地,如果您將 CommandType 設定為 adCmdTable 並呼叫 Execute 方法,ADO 會產生一個內部的查詢,選取由 CommandText 屬性所識別之資料表中所有的欄,並以語言事件提交給伺服器。另一方面,如果您將 CommandType 設定為 adStoredProc,呼叫 Execute 會導致 ADO 提交遠端程序呼叫給伺服器以執行列在 CommandText 屬性中的預存程序。

為什麼您要在意是以語言事件或以 RPC 提交要求給伺服器呢?您關心是因為一般而言,RPC 的效能較佳,特別是使用不同的篩選數值重複呼叫相同的查詢時。雖然 SQL Server 可以將純語言事件要求自動參數化,但是這樣做的能力仍然十分有限。它不會嘗試自動參數化某些類型的查詢。對於基本上相同的查詢這會導致不同的執行結果,而單純只因為不同的篩選值,而在伺服器上耗費計劃編輯的成本。通常這並不是您所想要的 — 對於第一次執行查詢您要編譯一個新的計劃,然後在後續發生對不同參數有重要作用的執行上重複使用該計劃。

另一方面,RPC 並不依賴伺服器而是使用明確地參數化來鼓勵計劃重複使用。程序第一次執行會產生一個計劃,即使提供參數不同的值,後續的執行仍會自動重複使用它。使用 RPC 來呼叫預存程序相對於使用語言事件,不僅節省計劃編輯所需的執行時間和 CPU 資源,加上因為避免在重複的執行計劃上浪費記憶體,所以也可以較妥善地利用 SQL Server 的記憶體資源。

這也是當執行動態 T-SQL 時,EXEC() 通常偏好 sp_executesql 的相同理由。Sp_executesql 的運作方式是使用特定的查詢來建立預存程序,然後再使用支援的參數來呼叫它。與 EXEC() 不同的是,sp_executesql 提供機制允許您參數化動態的 T-SQL 並且鼓勵計劃重複使用。使用 sp_executesql 執行的動態查詢比使用 EXEC() 執行的動態查詢,有較大的機會可以避免不必要的編輯和資源成本。

TDS

從用戶端傳送到 SQL Server 的 RPC、語言事件和其他類型的要求,都會格式化為 SQL Server 特定的資料格式,稱為「表格式資料串流 (TDS)」。TDS 是 SQL Server 用戶端和伺服器之間交談的「語言」。它的準確格式已無記載,但是用戶端如果要和 SQL Server 通訊就必須要會表達 TDS。

目前,SQL Server 支援三種版本的 TDS:TDS 8.0 (適用於 SQL 2000 用戶端)、TDS 7.0 (適用於 SQL Server 7.0 用戶端) 和 TDS 4.2 (適用於 SQL Server 4.2、6.0 和 6.5 用戶端)。唯一完全支援所有 SQL Server 2000 功能的版本是 TDS 8.0。其他的則是保留用於回溯相容性。

伺服器端網路程式庫

在伺服器端,用戶端的要求最初會由 SQL Server 設定來接聽特定網路通訊協定的接聽程式所接收。這些接聽程式包括伺服器上的網路程式庫和提供它們和伺服器之間導管功能的伺服器端網路程式庫。您可以使用伺服器網路公用程式來設定伺服器所要接聽的通訊協定。除了處理叢集之外,SQL Servers 支援和客戶端所支援同樣範圍的網路通訊協定。對於叢集的 SQL Server,只有 TCP/IP 和「具名管道」可用。

SQL Server 在其所接聽的用戶端要求上為每個網路通訊協定設定一個執行緒,並使用 Windows 的 I/O 完成通訊埠機制有效地等待並處理要求。當由網路上接收 TDS 封包後,網路程式庫接聽程式會將它們重新組譯成原來的用戶端要求,並傳遞到 SQL Server 的命令處理層,即「開放式資料服務 (ODS)」。

將結果傳回用戶端

當伺服器準備好要對特定用戶端要求傳回結果時,會使用最初收到要求時相同的網路堆疊。它會在伺服器端網路程式庫上將結果傳送到適當的網路通訊協定,接著依序在網路上以 TDS 格式送回給用戶端。

在用戶端上,伺服器接收的 TDS 封包會從 IPC 層使用用戶端網路程式庫重新組譯,然後轉送到啟始該要求的 API 或物件程式庫。

匯總

雖然牽涉到所有的部分, SQL Server 用戶端和伺服器之間的往返可以是相當快速的 — 回應時間在秒之下是很常見的,尤其是使用共用記憶體網路程式庫時。在此有幾個資料點是當您建立或微調自己的 SQL Server 用戶端應用程式時值得記住的:

  • 如果您的應用程式和 SQL Server 是在同一部機器上執行的話,倘若您尚未使用共用記憶體網路程式庫,請考慮使用。共用記憶體網路程式庫架構的連線通常比其他類型的連線快。不過,請記住我稍早所說的:在假設某解決方案天生就又好又快之前,請徹底進行測試並與可行的替代方案進行比較。好壞一試便知。
  • 因為用戶端在第一次連線時就被指定到特定的 UMS 排程器直到中斷連線為止,所以確認應用程式的工作量平均分配在建立到伺服器的各個連線上是很重要的。不平均的工作量可能導致不必要的 CPU 爭用和不盡理想的資源使用。
  • 您在伺服器上所設定以及用戶端所指定的預設網路封包大小,在連線時會直接影響到它們在伺服器上需要多少記憶體以及配置的集區。當您設定伺服器的延展性和速度時請記住這點。也請記住,在預設狀況下,ADO.NET 應用程式的網路封包大小會比 ADO 應用程式的大。
  • 一般而言,在傳送請求到伺服器時您應該優先選擇 RPC 而非語言事件。在您使用的 ADO 或 ADO.NET 物件設定適當的屬性以加速做到這一點。
  • 當執行動態 T-SQL 時,儘可能使用 sp_executesql 而非 EXEC()。唯一不可能的時候是當使用 EXEC() 的能力來將查詢的片段串連成超過可以儲存在單一本機變數的動態查詢字串時 (很罕見的狀況)。
  • 當您遭遇到用戶端的問題,並且懷疑是和您用來連接到伺服器的物件程式庫或 API 有關時,其中一個可用來疑難排解的技巧是,變更您正在使用的用戶端機制以將問題隔離到特定的元件。例如,假設您升級 MDAC,然後開始在您的 SQL Server 錯誤記錄檔看到編號 17805 的錯誤,指出接收到從用戶端 ADO 應用程式傳出的不正確 TDS 封包。如果不麻煩的話,您可以嘗試將應用程式切換成使用 ODBC 的 OLE DB 提供者,看看問題是否和 SQLOLEDB 提供者有關。反之,如果您的 ADO 架構應用程式是在 ODBC 上連線,您可以切換到 SQLOLEDB 看是否可以解決問題或至少可以縮小範圍。
  • 順著這些相同的思考軸線,就可以理解有時候在疑難排解與連線相關的問題時,為什麼要變更所使用的網路程式庫了。如果您使用的是 TCP/IP,或許「具名管道」值得一試。例如,您遭遇到 DHCP 伺服器的問題而且沒有有效的 IP 位址,您就無法使用 TCP/IP 連線到 SQL Server。經由切換到「具名管道」,您可以快速將問題隔離到 TCP/IP 的特定部分。另一方面,如果您切換網路程式庫而仍然有同樣的問題,您或許可以排除是網路程式庫的問題。或許是伺服器關閉或是在您和伺服器之間網路基本架構的某一部分運作不正常。即使什麼都沒有的話,能夠簡單的變更應用程式使用的網路程式庫而不用變更應用程式本身,就已經提供您有助於釐清問題的工具了。對您而言即使無法長期的使用特定的網路程式庫,暫時切換用戶端使用它也有助於縮小相關連線問題的範圍。

請評分: -3 -2 -1 +1 +2 +3
  
   

Hi-Fi優質I.T網”站內所有文章、圖片除特別加註外均屬本站所有,如有任何問題請來信告知
請支持言論自由,討論區所發表之言論不代表本站立場
Hi-Fi優質I.T網”版權所有2004©
---最佳顯示效果1024*768---