首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

ADO.NET 2.0 中的查詢通知(五):SqlCacheDependency 整合與最佳實務

     編輯:關於C語言

SqlNotificationRequest 的強大之處

使用 SqlNotificationRequest 的強大之處 (當然也包含額外工作) 在於由您自己等待與處理查詢通知。若使用 SqlDependency,則在接收查詢通知前甚至無需連接資料庫。事實上不需為了接收 SqlNotificationRequest 通知而等待;可定期輪詢訊息佇列。SqlNotificationRequest 另一用處是撰寫特殊應用程式,即使通知已啟動,該程式也不會執行。當程式啟動後,將連接到訊息佇列並決定快取中 (因上次執行) 哪些內容無效。

通知何時消失?

探討這類為等待通知需花費數小時或數天的應用程式:「如果資料不發生改變,通知何時消失?」唯一導致通知消失的情況 (如清理資料庫訂閱表) 就是通知被引發或通知過期。資料庫管理員若對始終留在資料庫中的訂閱 (因佔用 SQL 資源且增加查詢與資料更新成本) 感到困擾,可在 SQL Server 中手動清理通知。先查詢 SQL Server 2005 動態檢視找出不想要的通知訂閱,再用命令刪除:

-- 查看所有訂閱
SELECT * FROM sys.dm_qn_subscriptions
-- 選取要刪除的訂閱 ID,假設 ID = 42
KILL QUERY NOTIFICATION SUBSCRIPTION 42

在 ASP.NET 中使用 SqlCacheDependency

通知功能還連接到 ASP.NET 的 Cache 類別。ASP.NET 2.0 中 CacheDependency 類別可衍生子類別,其中 SqlCacheDependency 封裝了 SqlDependency,行為與 ASP.NET 中其他 CacheDependency 相同。SqlCacheDependency 超越 SqlDependency,因它可在 SQL Server 2005 或舊版 SQL Server 上運作。當然對舊版 SQL Server,實作完全不同。

若使用舊版 SQL Server,SqlCacheDependency 透過在被「監視」表上建立觸發器運作。觸發器將變更資訊記錄到另一張 SQL Server 表,然後輪詢那張表。可對啟用相依性功能的表與輪詢時間間隔進行設定。舊版實作細節超出本文範圍,詳見 Improved Caching in ASP.NET 2.0。

使用 SQL Server 2005 時,SqlCacheDependency 封裝一個與前面 ADO.NET 範例類似的 SqlDependency 實例。以下是簡短範例:

// 從 Page.Load 呼叫
CreateSqlCacheDependency(SqlCommand cmd)
{
    SqlCacheDependency dep = new SqlCacheDependency(cmd);
    Response.Cache.SetExpires(DateTime.Now.AddSeconds(60));
    Response.Cache.SetCacheability(HttpCacheability.Public);
    Response.Cache.SetValidUntilExpires(true);
    Response.AddCacheDependency(dep);
}

一個很棒且易用的特性是 SqlCacheDependency 可與頁面快取或頁面片段快取搭配。可透過特殊 ASP.NET 指示詞 OutputCache 宣告式啟用所有 SqlCommand 查詢通知功能。該方式為頁面中所有 SqlCommand 設定相同 SqlDependency。對 SQL Server 2005 資料庫宣告方式:

<%@ OutputCache SqlDependency="CommandNotification" ... %>

注意 CommandNotification 為關鍵字,意為「使用 SQL Server 2005 與 SqlDependency」。若用舊版 SQL Server,指示詞參數語法完全不同。同樣,只有在特定作業系統版本執行 ASP.NET 2.0 時,才啟用 CommandNotification 設定值。

熱心的通知

SQL Server 查詢通知設計策略:頻繁通知用戶總比忘記通知好。儘管大多數情況收到通知是因他人修改表中某列導致快取失效,但並非總是如此。例如 DBA 回收資料庫會收到通知。若查詢引用的任何表被修改、刪除、清空,也會收到通知。因查詢通知佔用 SQL Server 資源,若 SQL Server 面臨資源不足壓力,可能從內部表刪除查詢通知,此時客戶端也會收到通知。每個通知請求包含逾時值,訂閱逾時也會通知您。

若使用 SqlDependency,分派器會將所有資訊封裝到 SqlNotificationEventArgs 實例。該類別包含三個屬性:Info、Source、Type,幫助查明通知產生原因。若用 SqlNotificationRequest,佇列訊息的 message_body 欄位包含的 XML 文件也含相同資訊,但需自行用 XPath 或 XQuery 分析。以下是前面 ADO.NET SqlNotificationRequest 範例產生的 XML 範例:

<qn:QueryNotification
XMLns:qn="https://schemas.microsoft.com/SQL/Notifications/QueryNotification"
id="2" type="change" source="data" info="update"
database_id="6" user_id="1">
<qn:Message>{CFD53DDB-A633-4490-95A8-8E837D771707}</qn:Message>
</qn:QueryNotification>

注意:儘管通知產生因將 job_id = 5 這列的 job_desc 欄位值修改為 "new job",但在訊息主體永遠看不到這些資訊。通知能判斷某 SQL 陳述式修改資料導致結果集變化,但不夠聰明辨別 UPDATE 陳述式是否真正修改資料。例如將某列 job_desc = "new job" 修改成 job_desc = "new job" 會導致通知產生。同樣,因查詢通知是非同步且在執行 SQL 命令或批次時註冊,可能您還沒讀完結果集就收到通知。若提交查詢不符合規則,會立即收到通知。這些規則即前面提到的索引檢視規則。

何時不使用通知?

由於您已了解查詢通知運作原理,容易指出其用處:可重寫的唯讀表。每個通知佔用 SQL Server 資源,故在唯讀表上使用通知屬浪費與不經濟。此外勿用於臨時查詢,否則導致大量不同資料列集同時被「監視」。一個有用內部細節:SQL Server 會合併參數化查詢使用不同參數時佔用的通知資源。始終使用參數化查詢 (如上 SqlNotificationRequest 範例) 可利用此特性並獲得增強效能。若聽到這些勸言後擔心,請記住效能問題不代表無法收到恰當通知。若用 au_lname 當參數,user1 監視 au_lname 為 A-M 的 authors 資料而 user2 監視 N-Z,每個用戶只會收到針對其資料子集的「正確」通知。

最後注意:當某些人談論通知應用程式時,想像滿是股票經紀人的房間與不斷變化股價,每個顯示器不停變化。這樣用查詢通知絕對錯誤,原因有二:

  1. 資料列集不斷變化,網路將被大量查詢通知與查詢重新整理請求阻塞。
  2. 若有相當多用戶且都「監視」相同資料,每個通知將導致大量用戶同時重新查詢相同資料列集。大量對相同資料集查詢請求也可能導致 SQL Server 拒絕服務!

若覺得有些程式設計師會濫用該特性,可高興地告訴您 Beta2 後版本中,SQL Server 可透過動態管理檢視為 DBA 提供更多監視該特性資訊。目前這些檢視只能顯示訂閱資訊。請記住這種可能性始終存在:SQL Server 2005「判定」查詢通知佔用太多資源並開始清理它們。

結論

查詢通知是內建於 SQL Server 2005 的強大新特性,可直接在 ADO.NET 2.0 與 ASP.NET 2.0 中使用。儘管 ADO.NET 特性 (SqlNotificationRequest 與 SqlDependency) 僅能在 SQL Server 2005 資料庫運作,但 ASP.NET 透過池機制使該特性「向後相容」。請謹慎正確使用該特性,牢記其含義與影響。對該特性而言最佳「甜點」就是 ASP.NET 中那些可能被其他應用程式 (當然包含 Web 應用) 更新的可重寫唯讀表。對此應用情境,查詢通知提供程式設計師們盼望多年的解決方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved