簡體   English   中英

SQL Server CLR線程

[英]SQL Server CLR Threading

我一直在努力使用SQL Server CLR存儲過程。

背景:

我們正在使用SQL Server 2014,並且已實現調用客戶Web服務的CLR存儲過程。

最初使用線程不會減慢SQL Server CLR的主線程。

雖然,現在,我知道在CLR下使用線程並不是最好的主意,但它已經正常工作了6年(自SQL Server 2008以來)。 它最近已遷移到SQL Server 2014。

問題

在我的開發機器上,與測試系統一樣,我們對解決方案沒有任何問題。

在客戶系統上,調用Web服務的線程由於某種原因從不執行。

我可以從日志文件中看到一切正常,直到線程執行。

沒有特定的錯誤,沒有。

我們一直在嘗試更改權限,但沒有成功。 因此,我認為這不是一個許可問題。

問題

  1. 有誰知道如何改變行為? 我們找不到任何可能起作用的配置。

  2. 完全刪除線程,並直接在SQL Server主線程上調用Web服務是否是個好主意?

謝謝你的任何建議,彼得

對問題#1不確定,但考慮到問題#2的建議可能無關緊要。 盡管如此,SQL Server 2008(它工作的地方)和SQL Server 2014(它不工作的地方)之間的一個區別是SQL Server鏈接到的CLR版本。 SQL Server 2005/2008 / 2008 R2鏈接到CLR v2.0,而SQL Server 2012和更新版本鏈接到CLR v 4.0。 由於您沒有看到錯誤而您的客戶端是,我將確保他們的系統已更新為您正在運行的相同.NET Framework版本。

對於問題#2,我建議刪除多線程。 這有太多潛在的問題,需要大會UNSAFE 如果刪除線程,則可以將Assembly設置為EXTERNAL_ACCESS

如果要減少爭用,那么假設Web服務調用屬於同一URI,則需要增加允許的並發Web請求數。 這可以通過設置ServicePointManager.DefaultConnectionLimit屬性來完成。 默認值為2.這意味着,任何其他請求將等待並等待當前2之一關閉。

另外,請務必正確Dispose WebRequest


關於進行可能無法快速完成的外部調用(即Web服務)的擔憂是SQL Server使用協作式多任務處理,其中每個線程負責在各個​​點處“控制”控制回到調度程序(有效地暫停它),以便調度程序可以隨機播放並運行其他正在“休眠”的內容。 通常可以通過執行以下至少一項來減輕對SQLCLR代碼的關注:

  • 執行數據訪問/查詢實例
  • 調用thread.sleep(0);

但是,外部調用不進行數據訪問,並且在等待WebResponse完成時無法輕松調用thread.sleep(0) 是的,您可以在單獨的線程上調用WebService,並在等待它完成時,假設您只是循環和檢查, sleep(x)將允許yield。

但是異步進行Web服務調用是否必要? 它的缺點當然是要求將程序集標記為WITH PERMISSION_SET = UNSAFE 這在很大程度上取決於呼叫通常需要多長時間,以及呼叫的頻率。 調用越頻繁,任何延遲的可能性越大,至少部分是由每個URI允許的並發連接數的低默認值引起的。 這與我在頂部提出的建議有關。

但是如果你想看看SQL Server實際上是如何工作的,那么這應該很容易測試。 在我的筆記本電腦上,我去了對象瀏覽器中的服務器“屬性”,轉到“處理器”,取消選中“自動設置處理器關聯...”選項,在樹視圖中的“處理器關系”下只選擇了一個CPU。在對話框的中間,單擊“確定”,然后重新啟動該服務。 然后,我建立了一個網頁,除了呼叫“睡眠”60秒之外什么也沒做。 我有一個調用網頁的SQLCLR TVF,所以我在兩個不同的標簽/會話中同時運行它。 在第3個標簽/會話中,我跑了:

SELECT SUM(so1.[schema_id]), so1.[type_desc], so2.[type_desc]
FROM sys.objects so1
CROSS JOIN sys.objects so2
CROSS JOIN sys.objects so3
CROSS JOIN sys.objects so4
CROSS JOIN sys.objects so5
WHERE so3.[create_date] <> so4.[modify_date]
GROUP BY so1.[type_desc], so2.[type_desc], so5.[name]
ORDER BY so2.[type_desc], so5.[name] DESC;

最后,在第4個選項卡中,在開始前3個后,我運行以下命令來監控系統:

SELECT * FROM sys.dm_os_schedulers WHERE [scheduler_id] = 0;

SELECT *
FROM sys.dm_exec_requests
WHERE [scheduler_id] = 0
AND [status] <> N'background'
ORDER BY [status] DESC, session_id;

運行SQLCLR函數的2個會話的狀態始終為“正在運行”,並且在選項卡3中運行該丑陋查詢的會話的狀態始終為“可運行”。 但只是為了確定,當兩個SQLCLR函數都沒有執行時再次運行那個丑陋的查詢,與運行SQLCLR調用的2個會話同時運行時所執行的1分14秒相同。持續60秒。

請不要推斷運行SQLCLR代碼進行Web調用沒有任何成本。 由於這些線程一直很忙,如果系統繁忙,那么它會降低SQL Server分配這些線程以更快地完成其他查詢的能力。 但似乎可以肯定地得出結論,至少在負載低到中等的系統上,通過添加線程獲得的好處似乎不值得增加復雜性的成本(特別是因為現在還有一個尚未重現的調試問題)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM