本文討論在 Microsoft SQL Server 2014 中查詢叢集資料行存放區索引期間發生的問題。 本文提供這個問題 的解決方案 。
摘要
當您使用的查詢掃描 Microsoft SQL Server 2014 中的叢集資料行存放區索引時,在極少數情況下,您可能會收到部分查詢結果。
執行下列作業時會發生此問題。
步驟 1
Transact-SQL 陳述式 [INSERT 或 BULK-INSERT] 會將資料插入具有叢集資料行存放區索引的資料表中。 在此作業期間,適用下列條件:
- 當 Transact-SQL 陳述式達到資料列群組閾值時,會關閉具有區段 S1 的資料列群組 R1。
- 區段 S1 指向本機字典 D1。
- 陳述式會繼續將列插入新的資料列群組 R2。
- 當資料列群組 R1 關閉時,也不必關閉本機字典 D1。 如果字典 D1 仍有可用空間,您可以將它保持開啟,並重複用於新的資料列群組 R2。
步驟 2
如果 Transact-SQL 陳述式在關閉新資料列群組 R2 之前異常結束或取消,則適用下列條件:
- 資料行存放區中繼資料變更發生在獨立於外部交易認可的子交易中。
- 此時,資料列群組 R1 會以「建置中」或 INVISIBLE 狀態持續存在於系統資料表中,而區段 S1 會參照字典 D1。
- 系統資料表中未為字典 D1 建立任何資料列。 這是因為 Transact-SQL 陳述式永遠沒有機會關閉現有的資料列。 因此,現有的資料列會持續存在。
步驟 3
在一般情況下,如果 Tuple Mover 背景工作在 Transact-SQL 陳述式結束之後啟動,背景工作會移除不可見的資料列群組 R1 和區段 S1。 如果現在啟動新的 Transact-SQL 陳述式,並建立資料列群組 R3,其中包含需要新本機字典的新區段 S3,則您無法重複使用字典 D1 的內部識別碼。 這是因為資料行存放區的記憶體內部狀態會持續追蹤所使用的字典識別碼。 因此,區段 S3 將參考新字典 D2。
注意:此步驟中的條件是常見條件。 因此不會發生損毀。
步驟 4
如果SQL Server在元組移動器工作生效之前失去字典 D1 的記憶體內部狀態,並按照步驟 3) 中的說明執行 (,則會發生本文所述的問題。
記事
發生此事件的原因如下:
- SQL Server 發生記憶體超載,而且字典 D1 的記憶體內部內容會從記憶體中收回。
- SQL Server 的執行個體隨即重新啟動。
- 包含叢集資料行存放區索引的資料庫會離線,然後又回到線上。
發生上述任何一個事件且 SQL Server 重新載入記憶體內部結構之後,就不會有字典 D1 及其內部識別碼存在的記錄。 這是因為在 Transact-SQL 陳述式結束或加速時,字典 D1 未保留在系統資料表中。
如果 Tuple Mover 背景工作在此時啟動,則不會發生錯誤,因為適用步驟 3 中所述的條件。
如果在元組移動器背景工作開始之前建立新的資料列群組 R3 (根據上一個項目符號項目) ,SQL Server 會將相同的內部識別碼指派給新的字典 D1,並參照資料列群組 R3 中區段 S3 的字典 D1。
當元組移動器背景工作在上一個動作之後啟動時,它會刪除不可見的資料列群組 R1 及其區段 S1,以及新的字典 D1。 這是因為元組移動程式認為新字典 D1 和 S1 參照的原始字典 D1 相同。
注意:發生這種情況時,您無法查詢資料列群組 R3 的內容。
解決方式
此問題已先在下列 SQL Server 累積更新中修正:
SQL Server 2014 SP1 累積更新 1
SQL Server 2014 的累積更新 8
此問題的修正程式也包含在下列一般發行版本 (GDR) 更新中:
SQL Server 2014 QFE 的安全性更新
此更新包括累積更新 8、此重要修正程式,以及必要的 MS15-058 安全性更新。
SQL Server 2014 GDR 的安全性更新
此更新包含此重要修正程式,以及透過 MS15-058 累積安全性修正程式。
SQL Server 2014 Service Pack 1 GDR 的非安全性更新
此更新只包含這個重要修正程式。
關於 SQL Server 的累積更新
SQL Server 的每個新累積更新都包含所有 Hotfix 和先前累積更新的所有安全性修正程式。 查看 SQL Server 的最新累積更新:
更多資訊
錯誤訊息在目前受影響的資料庫中,如果您在套用此修正程式之後執行 DBCC CHECKDB,會收到下列錯誤訊息:
注意
Msg 5289, Level 16, State 1, Line 1
資料表 't' 上的叢集資料行存放區索引 'cci' 有一或多個不符合字典中的資料值。 從備份還原資料。
在目前受影響的資料庫中,當您執行查詢以在套用此修正程式之後掃描受影響的資料表時,您會收到下列錯誤訊息:
注意
Msg 5288, Level 16, State 1, Line 1
資料行存放區索引有一或多個不符合字典中的資料值。 如需詳細資訊,請執行 DBCC CHECKDB。
如果您收到這些錯誤,您可以大量匯出未受影響的資料行/資料列群組的資料,然後在捨棄或建立叢集資料行存放區索引後重新載入資料,以儲存未損毀的資料。 您應該啟用追蹤旗標 10207 以隱藏 5288 錯誤,並還原為略過損毀資料列群組的舊行為。
注意:這個具有區段 S3 的資料列群組 R3 會產生錯誤訊息 5288 和 5289。 追蹤旗標 10207 用於擷取不受遺失字典 D1 影響的資料列群組 R3 區段。
查詢受影響的資料庫若要判斷包含資料行存放區索引的資料庫是否已受到此問題的影響,請執行下列查詢:
select
object_name(i.object_id) as table_name,
i.name as index_name,
p.partition_number,
count(distinct s.segment_id) as damaged_rowgroups
from
sys.indexes i
join sys.partitions p on p.object_id = i.object_id and p.index_id = i.index_id
join sys.column_store_row_groups g on g.object_id = i.object_id and g.index_id = i.index_id and g.partition_number = p.partition_number
join sys.column_store_segments s on s.partition_id = p.partition_id and s.segment_id = g.row_group_id
where
i.type in (5, 6)
and s.secondary_dictionary_id <> -1
and g.state_description = 'COMPRESSED'
and s.secondary_dictionary_id not in
(
select dictionary_id from sys.column_store_dictionaries d
where d.hobt_id = p.hobt_id and d.column_id = s.column_id
)
group by
object_name(i.object_id),
i.name,
p.partition_number
記事
您必須在執行 SQL Server 的伺服器上,針對包含資料行存放區索引的每個資料庫執行此查詢。 空結果集表示資料庫不受影響。
在沒有活動會建立新資料列群組或變更現有資料列群組狀態的期間執行此查詢。 例如,下列活動可以修改資料列群組的狀態:索引建置、索引重組、大量插入、元組移動器壓縮差異存放區。
在執行查詢之前,可以使用追蹤旗標 634 停用背景 Tuple Mover 工作。 使用此命令停用背景工作:DBCC TRACEON ( 634 , -1 ) 。 查詢執行完畢後,請記得使用命令重新啟用背景工作:DBCC TRACEOFF ( 634 , -1 ) 。
此外,請確定在此查詢執行時,沒有 BULK INSERT/BCP/SELECT-INTO 命令將資料插入使用資料行存放區索引的資料表。
建議使用這些步驟來防止查詢傳回誤判。
狀態
Microsoft 已確認這是「適用對象」一節中列出的 Microsoft 產品中的問題。