SQLCLR 使用者定義類型 (UDT) SCH-M 阻塞
我希望有人可以就我在 C# SQLCLR UDT 上的模式鎖定問題提供一些指導。我已經在 Internet 上花費了很長時間來研究我的問題,但沒有成功找到解決方案。
此外,這個“可能”是一個連結伺服器問題,因為我們看到訪問 UDT 的連結伺服器查詢似乎會阻止查詢(sch-m在遠端伺服器上執行)。
背後故事:
早在 2006 年,我們就開始將一些 DB2 程序向下移植到 SQL Server 2005(從那時起我們已經升級到 SQL 2008,但仍然需要將我們的 UDT 用於許多目前程序)。在 DB2 中,我們廣泛使用了 DB2
TIMESTAMP
數據類型**——CCYY-MM-DD.HH.MM.SS.mmmmmm——**它的精度可以達到微秒。因為當時 SQL Server 沒有DATETIME2
,我們被迫創建自己的 C# SQLCLR UDT 來模擬 DB2TIMESTAMP
。UDT 是VARBINARY
使用允許我們引用以下內容的屬性創建的:Column.Timestamp (CCYY-MM-DD.HH.MM.SS.mmmmm) Column.Date (CCYY-MM-DD) Column.Microsecond (mmmmmm) Etc.
當多個程序僅使用列名(不引用特定屬性)訪問 UDT 時,我們似乎沒有問題。
但是,當我們有多個程序訪問 UDT 並引用其中一個屬性(
.Timestamp
等)時,我們會遇到Sch-M鎖,並且其他程序也訪問該 UDT 被迫等待。我承認我對 CLR 和 UDT 的所有知識了解有限。
我只是不明白為什麼我們在僅選擇列並指定基礎屬性之一的同時獲得模式修改鎖。
我會很感激你可能有的任何建議。
謝謝,
當您跨數據庫使用 SQL CLR 對象時,如果滿足某些條件,SQL Server 將自動轉換它們 ( https://technet.microsoft.com/en-us/library/ms178069(v=sql.105).aspx )。
就我而言,這種自動轉換正在取出 SCH-M 鎖。我通過手動將我的 SQL CLR 類型的內容轉換為二進制並將其作為
varbinary(max)
. 然後我在第二個數據庫中反序列化回我的 CLR 類型。
在訪問其任何屬性或方法時(在 UDT 本身上)具有架構鎖是有意義的,但在訪問基
VARBINARY
值時則不然。訪問基值時,它只是一VARBINARY
組不需要任何特殊解釋和/或處理的字節。但是,當訪問使用者定義類型 (UDT) 的任何屬性或方法時,它會訪問基礎VARBINARY
字節並根據該屬性或方法的程式碼返回其對該值的解釋(甚至可能更改基礎VARBINARY
值) . 如果沒有模式鎖(在 UDT 上),則可以在ALTER ASSEMBLY
引用這些屬性或方法之一的查詢執行時更改 UDT 的定義,這將允許在單個結果集中跨行更改對持久值的解釋,從而為您提供不一致或至少不可靠的結果。話雖如此,我一直無法重現獲得Sch-M(模式修改)鎖的場景。我嘗試了 Table 的多種變體,其中 UDT 列位於“目前”數據庫中、另一個數據庫中,或通過遠端訪問
OPENQUERY
,以及作為單獨的語句並處於顯式事務中。我還嘗試通過其中一種方法選擇 UDT,並嘗試使用UPDATE
UDT 列。我什至嘗試將 UDT 添加到另一個數據庫,創建Database2
“目前”數據庫,為 UDT 聲明一個局部變數,然後將該 UDT 變數插入到Database1
. 所有變體都導致只有一個Sch-S(架構穩定性)鎖定在 UDT 上。目前我能想到的唯一可能解釋Sch-M鎖的事情(而且我還沒有嘗試過)是:
- 呼叫標記為“mutator”的方法(我對此表示懷疑,因為您只提到了選擇屬性)。
不簽署大會(即不給它一個“強名稱”)。我見過簽署大會有好處的其他情況,即使它永遠不會被標記為EXTERNAL_ACCESS
or 或UNSAFE
。如果是這種情況,並且最終成為原因,那麼我懷疑整體原因是額外的預防措施是必要的,因為 SQL Server 沒有內部方法來保證沒有該簽名的 UDT 的定義。SQL Server 2008 中有些不同。我認為這不會有什麼不同(我認為不會,但也不能在沒有測試的情況下排除),但我在 SQL Server 2012 SP3 上進行了測試,並且報告了這個問題使用 SQL Server 2008。我現在已經使用未簽名的程序集進行了測試,並且在 SQL Server 2008 R2(帶有未簽名的程序集)中僅本地/無連結伺服器,以及在 SQL Server 2005 SP4(也帶有未簽名的程序集)中本地和循環-返回 連結伺服器。在任何情況下採用的唯一模式鎖是Sch-S鎖。我看不到使用 UDT 會取出Sch-M鎖的任何方式,也看不到任何理由,因為Sch-S鎖可以滿足需要。
我懷疑在訪問 UDT 的同時發生了其他事情,而且看起來問題在於 UDT。無論是那個還是 UDT 所做的不僅僅是簡單的
DateTime
操作。為了弄清楚這一點,它需要:
- UDT 程式碼
- 正在訪問的查詢
- 連結伺服器定義
- 查看獲得Sch-M鎖的特定鎖資源。
不幸的是,聽起來這種環境(可能還有問題本身)不再可以從中獲取此類資訊。