共用方式為


監控和排除故障以加速資料庫復原

適用於:Microsoft Fabric 中的 SQL Server 2019 (15.x) 和更新版本 Azure SQL 資料庫 Azure SQL 受控執行個體SQL Database

本文可協助您監視、診斷及解決 SQL Server 2019 (15.x)和更新版本、Azure SQL 受控實例、Azure SQL Database,以及 Microsoft Fabric 中的 SQL 資料庫的加速資料庫復原(ADR)問題。

檢查 PVS 的大小

使用 sys.dm_tran_persistent_version_store_stats DMV 來識別永續性版本存放區 (PVS) 大小是否大於預期。

下列範例診斷查詢會顯示目前 PVS 大小、清除程式,以及所有 PVS 大小大於零之資料庫中的其他詳細數據:

SELECT pvss.database_id,
       DB_NAME(pvss.database_id) AS database_name,
       pvss.persistent_version_store_size_kb / 1024. / 1024 AS persistent_version_store_size_gb,
       100 * pvss.persistent_version_store_size_kb / df.total_db_size_kb AS pvs_percent_of_database_size,
       df.total_db_size_kb / 1024. / 1024 AS total_db_size_gb,
       pvss.online_index_version_store_size_kb / 1024. / 1024 AS online_index_version_store_size_gb,
       pvss.current_aborted_transaction_count,
       pvss.aborted_version_cleaner_start_time,
       pvss.aborted_version_cleaner_end_time,
       pvss.oldest_aborted_transaction_id,
       pvss.oldest_active_transaction_id,
       dt.database_transaction_begin_time AS oldest_transaction_begin_time,
       asdt.session_id AS active_transaction_session_id,
       asdt.elapsed_time_seconds AS active_transaction_elapsed_time_seconds,
       pvss.pvs_off_row_page_skipped_low_water_mark,
       pvss.pvs_off_row_page_skipped_min_useful_xts,
       pvss.pvs_off_row_page_skipped_oldest_aborted_xdesid
FROM sys.dm_tran_persistent_version_store_stats AS pvss
CROSS APPLY (
            SELECT SUM(size * 8.) AS total_db_size_kb
            FROM sys.master_files AS mf
            WHERE mf.database_id = pvss.database_id
                  AND
                  mf.state = 0
                  AND
                  mf.type = 0
            ) AS df
LEFT JOIN sys.dm_tran_database_transactions AS dt
ON pvss.oldest_active_transaction_id = dt.transaction_id
   AND
   pvss.database_id = dt.database_id
LEFT JOIN sys.dm_tran_active_snapshot_database_transactions AS asdt
ON pvss.min_transaction_timestamp = asdt.transaction_sequence_num
   OR
   pvss.online_index_min_transaction_timestamp = asdt.transaction_sequence_num
WHERE pvss.persistent_version_store_size_kb > 0
ORDER BY persistent_version_store_size_kb DESC;

請檢查 [pvs_percent_of_database_size] 數據行,以查看相對於資料庫大小總計的 PVS 大小。 請注意一般 PVS 大小與在典型應用程式活動期間所見基線之間的任何差異。 如果 PVS 明顯大於基準,或接近資料庫大小的 50%,則 PVS 會被視為很大。

如果 PVS 的大小未減少,請使用下列疑難解答步驟來尋找並解決大型 PVS 大小的原因。

小提示

下列疑難解答步驟中提及的數據行會參考本節中診斷查詢結果集中的數據行。

PVS 尺寸較大可能是因為下列任何原因導致:

檢查長時間執行的正在進行的交易

長時間運行的活動交易會阻止已啟用 ADR 的資料庫執行 PVS 清理。 使用 oldest_transaction_begin_time 欄位檢查最舊的活躍交易開始時間。 若要尋找長時間執行的交易,請使用下列範例查詢。 您可以設定交易持續時間的臨界值和產生的事務歷史記錄量:

DECLARE @LongTxThreshold int = 900;  /* The number of seconds to use as a duration threshold for long-running transactions */
DECLARE @LongTransactionLogBytes bigint = 1073741824; /* The number of bytes to use as the generated log threshold for long-running transactions */

SELECT  dbtr.database_id,
        DB_NAME(dbtr.database_id) AS database_name,
        st.session_id,
        st.transaction_id,
        atr.name,
        sess.login_time,
        dbtr.database_transaction_log_bytes_used,
        CASE WHEN GETDATE() >= DATEADD(second, @LongTxThreshold, tr.transaction_begin_time) THEN 'DurationThresholdExceeded'
             WHEN dbtr.database_transaction_log_bytes_used >= @LongTransactionLogBytes THEN 'LogThresholdExceeded'
             ELSE 'Unknown'
        END
        AS reason
FROM sys.dm_tran_active_transactions AS tr
INNER JOIN sys.dm_tran_session_transactions AS st
ON tr.transaction_id = st.transaction_id
INNER JOIN sys.dm_exec_sessions AS sess
ON st.session_id = sess.session_id
INNER JOIN sys.dm_tran_database_transactions AS dbtr
ON tr.transaction_id = dbtr.transaction_id
INNER JOIN sys.dm_tran_active_transactions AS atr
ON atr.transaction_id = st.transaction_id
WHERE GETDATE() >= DATEADD(second, @LongTxThreshold, tr.transaction_begin_time)
      OR
      dbtr.database_transaction_log_bytes_used >= @LongTransactionLogBytes;

若已識別會話,請考慮在情況允許時終止會話。 檢閱應用程式,以判斷有問題的交易本質,以避免未來發生問題。

如需了解針對長時間查詢的疑難排解方法詳細資訊,請參閱:

檢查長時間執行的作用中快照集掃描

長時間運行的活躍快照掃描可能會阻止在啟用了 ADR 的資料庫中進行 PVS 清理。 使用 READ COMMITTED 快照隔離 (RCSI) 或 SNAPSHOT隔離等級 的語句,接收實例層級時間戳。 快照集掃描會使用時間戳來判斷 RCSI 或 SNAPSHOT 交易的版本數據列可見性。 使用 RCSI 的每個語句都有自己的時間戳,而 SNAPSHOT 隔離具有事務層級的時間戳。

這些實例層級的交易時間戳即使在單一資料庫交易中使用,因為任何交易都可能會升階為跨資料庫交易。 因此,快照掃描可以防止在同一資料庫引擎實例上的任何資料庫中進行 PVS 清除。 同樣地,即使未啟用 ADR,快照掃描也可以防止清理 tempdb 中的版本儲存區。 因此,當有使用 SNAPSHOT 或 RCSI 的長期執行交易時,PVS 的規模可能會增大。

pvs_off_row_page_skipped_min_useful_xts 欄會顯示因長時間快照檢查而略過的頁面數目。 如果此欄顯示高數值,則表示長時間的快照掃描正在阻止 PVS 清除。

使用下列範例查詢來尋找具有長時間執行 SNAPSHOT 或 RCSI 交易的工作階段:

SELECT sdt.transaction_id,
       sdt.transaction_sequence_num,
       s.database_id,
       s.session_id,
       s.login_time,
       GETDATE() AS query_time,
       s.host_name,
       s.program_name,
       s.login_name,
       s.last_request_start_time
FROM sys.dm_tran_active_snapshot_database_transactions AS sdt
INNER JOIN sys.dm_exec_sessions AS s
ON sdt.session_id = s.session_id;

為防止 PVS 清理延遲問題:

  • 如果可能的話,請考慮終止正在運行的長時間交易工作階段,因為它導致 PVS 清理延遲。
  • 優化長時間執行的查詢,以縮短查詢時間。
  • 檢閱應用程式以判斷問題活動快照掃描的性質。 請考慮對延遲 PVS 清理的長時間執行查詢使用不同的隔離級別,例如 READ COMMITTED,而非 SNAPSHOT 或 RCSI。 此問題會在隔離等級 SNAPSHOT 更頻繁地發生。
  • 在 Azure SQL Database 彈性集區中,請考慮使用 SNAPSHOT 隔離或 RCSI 將長時間執行交易的資料庫移出彈性集區,以避免相同集區中其他資料庫的 PVS 清除延遲。

檢查次要副本上執行時間過長的查詢

如果資料庫有次要複本,請檢查次要低水位標記是否正在前進。

pvs_off_row_page_skipped_low_water_mark 欄位中的大值可能表明因為次要複本上長時間執行的查詢而導致的清理延遲。 除了造成 PVS 清除的延遲之外,次要副本上的長時間查詢也可能造成鬼物清除的延遲。

您可以在主要副本上使用以下範例查詢,以找出次要副本上執行時間較長的查詢是否可能阻止 PVS 清除。 如果寫入工作負載正在主要副本上運行,但 low_water_mark_for_ghosts 欄中的值從一次執行範例查詢到下一次執行都沒有增加,那麼可能是次要副本上的長時間運行查詢正在阻礙 PVS 和 ghost 清除作業。

SELECT database_id,
       DB_NAME(database_id) AS database_name,
       low_water_mark_for_ghosts,
       synchronization_state_desc,
       synchronization_health_desc,
       is_suspended,
       suspend_reason_desc,
       secondary_lag_seconds
FROM sys.dm_hadr_database_replica_states
WHERE is_local = 1
      AND
      is_primary_replica = 1;

如需詳細資訊,請參閱 low_water_mark_for_ghosts 數據行的描述。

連接到每個可讀取的次要副本,找出正在執行長時間查詢的會話,如果有設定允許,考慮終止該會話。 如需詳細資訊,請參閱 查找緩慢查詢

檢查大量中止的交易

檢查 aborted_version_cleaner_start_timeaborted_version_cleaner_end_time 數據行,以查看最後一次中止的交易清除是否已完成。 oldest_aborted_transaction_id 應會在中止交易清除完成後向更高的方向移動。 如果 oldest_aborted_transaction_id 遠低於 oldest_active_transaction_id,且 current_abort_transaction_count 值很大,則可能有舊的中止交易正在阻止 PVS 清除。

若要解決由於大量中止交易而導致 PVS 清除延遲的問題,請考慮下列事項:

  • 如果您使用 SQL Server 2022 (16.x),請增加 ADR Cleaner Thread Count 伺服器組態的值。 如需詳細資訊,請參閱 伺服器組態:ADR 清除器線程計數
  • 可能的話,請暫停工作負載,以便版本清理程序能夠順利進行。
  • 檢閱應用程式,以識別並解決高交易中止率問題。 中止可能由於高比率的死結、重複索引鍵、約束條件違反或查詢超時。
  • 優化工作負載,以減少與 PVS 清除程式所需的物件層級或數據分割層級IX鎖定不相容的鎖定。 如需更多資訊,請參閱 鎖相容性
  • 如果使用 SQL Server,為了緊急控制 PVS 大小,請暫時停用 ADR。 請參閱 停用 ADR
  • 如果使用 SQL Server,且中止的交易清理最近未能成功完成,請檢查錯誤日誌中是否有報告 VersionCleaner 問題的訊息。
  • 即使在清理完成後,如果 PVS 大小沒有如預期地減少,請檢查 pvs_off_row_page_skipped_oldest_aborted_xdesid 欄位。 大型數值表示中止的交易中的行版本仍然佔用空間。

控制 PVS 大小

如果您有大量 DML 語句的工作負載(INSERTUPDATEDELETEMERGE),例如高容量 OLTP,並觀察 PVS 大小很大,您可能需要增加 ADR Cleaner Thread Count 伺服器組態的值,以控制 PVS 大小。 如需詳細資訊,請參閱 伺服器組態:ADR 清除器線程計數,從 SQL Server 2022 (16.x) 開始提供。

在 SQL Server 2019 (15.x)中,如果調高 ADR Cleaner Thread Count 組態的值仍無法充分降低 PVS 的大小,則可能需要暫停工作負載一段時間或進行復原,以便讓 PVS 清理過程能夠有效回收空間。

若要在工作負載之間或維護期間手動啟動 PVS 清除程序,請使用系統預存程序 sys.sp_persistent_version_cleanup

例如:

EXEC sys.sp_persistent_version_cleanup [WideWorldImporters];

進行中的交易可能會防止 PVS 清理程序啟動。 如果發生這種情況,執行 sys.sp_persistent_version_cleanup 預存程式的會話會以 PVS_CLEANUP_LOCK 等候類型進行等待。 您可以等候交易完成,也可以考慮盡可能終止使用中交易的封鎖程序會話。

紀錄清除失敗

從 SQL Server 2022 (16.x) 開始,錯誤記錄檔中會記錄值得注意的 PVS 清除訊息。 清理統計數據也會由tx_mtvc2_sweep_stats擴展事件報告。