Устранение неполадок ускоренного восстановления баз данных
Область применения:SQL Server 2019 (15.x) и более поздние версии База данных SQL Azure Управляемый экземпляр SQL Azureбазе данных SQL в Microsoft Fabric
Эта статья помогает диагностировать проблемы с ускоренного восстановления базы данных (ADR) в SQL Server 2019 (15.x) и более поздних версиях, Управляемом экземпляре SQL Azure, базе данных SQL Azure и базе данных SQL в Microsoft Fabric.
Исследуйте размер PVS
Используйте sys.dm_tran_persistent_version_store_stats DMV, чтобы определить, превышает ли размер хранилища постоянных версий (PVS) ожидаемый.
В следующем примере запроса показаны сведения о текущем размере PVS, процессах очистки и других деталях:
SELECT 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_pct_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,
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.database_files
WHERE state = 0
AND
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.database_id = DB_ID();
Проверьте столбец pvs_pct_of_database_size
, чтобы просмотреть размер PVS относительно общего размера базы данных. Обратите внимание на разницу от типичного размера PVS по сравнению с базовыми показателями, которые наблюдались в других периодах активности приложения. PVS считается большим, если он значительно больше базового уровня или если он близок к 50% размера базы данных. Чтобы найти причину большого размера PVS, выполните следующие действия по устранению неполадок.
Если размер PVS больше ожидаемого, проверьте:
- длительные активные транзакции
- Длительные сканирования активных моментальных снимков
- продолжительные запросы на вторичных репликах
- Прерванные транзакции
Проверка на наличие длительных активных транзакций.
Длительные активные транзакции могут предотвратить очистку PVS в базах данных с включенным ADR. Проверьте время начала самой старой активной транзакции с помощью столбца oldest_transaction_begin_time
. Дополнительные сведения о длительных транзакциях см. в следующем примере запроса. Пороговые значения для длительности транзакции и объема созданного журнала транзакций можно задать:
DECLARE @LongTxThreshold int = 1800; /* 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 a log amount threshold for long-running transactions */
SELECT dbtr.database_id,
transess.session_id,
transess.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 transess
ON tr.transaction_id = transess.transaction_id
INNER JOIN sys.dm_exec_sessions AS sess
ON transess.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 = transess.transaction_id
WHERE GETDATE() >= DATEADD(second, @LongTxThreshold, tr.transaction_begin_time)
OR
dbtr.database_transaction_log_bytes_used >= @LongTransactionLogBytes;
Если это разрешено, рассмотрите возможность завершения сеанса. Просмотрите приложение, чтобы определить характер проблемных активных транзакций, чтобы избежать проблемы в будущем.
Дополнительные сведения об устранении неполадок с длительными запросами см. в следующем разделе:
- Устранение неполадок с медленными выполнением запросов в SQL Server
- Обнаруженные типы узких мест производительности запросов в базе данных SQL Azure
- Обнаруженные типы узких мест производительности запросов в SQL Server и Управляемом экземпляре SQL Azure
Проверьте длительные активные сканирования моментальных снимков
Длительные проверки активных моментальных снимков могут предотвратить очистку PVS в базах данных с включенным ADR. Инструкции, использующие изоляцию моментальных снимков READ COMMITTED
(RCSI) или уровни изоляции SNAPSHOT
, получают метки времени на уровне экземпляра. Проверка моментального снимка использует метку времени для определения видимости строки версии для транзакции RCSI или SNAPSHOT
. Каждая инструкция с использованием RCSI имеет собственную метку времени, в то время как изоляция SNAPSHOT
имеет метку времени уровня транзакции.
Эти метки времени транзакций уровня экземпляра используются даже в транзакциях с одной базой данных, так как любая транзакция может запрашивать транзакцию между базами данных. Таким образом, сканирование моментальных снимков может предотвратить очистку PVS в любой базе данных в одном экземпляре ядра СУБД. Аналогичным образом, если ADR не включен, сканирование моментальных снимков может предотвратить очистку хранилища версий в tempdb
. В результате PVS может увеличиваться в размере, если существуют длительные транзакции, использующие SNAPSHOT
или RCSI.
В запросе в начале этой статьи в столбце pvs_off_row_page_skipped_min_useful_xts
отображается количество страниц, пропущенных при восстановлении из-за длительного сканирования моментальных снимков. Если в этом столбце отображается значение больше нормального, это означает, что длительное сканирование моментальных снимков предотвращает очистку PVS.
Используйте следующий пример запроса, чтобы найти сессию с длительной транзакцией SNAPSHOT
или RCSI.
SELECT snap.transaction_id,
snap.transaction_sequence_num,
session.session_id,
session.login_time,
GETUTCDATE() AS [now],
session.host_name,
session.program_name,
session.login_name,
session.last_request_start_time
FROM sys.dm_tran_active_snapshot_database_transactions AS snap
INNER JOIN sys.dm_exec_sessions AS session
ON snap.session_id = session.session_id
ORDER BY snap.transaction_sequence_num ASC;
Чтобы предотвратить задержки в процессе очистки PVS:
- Если это возможно, рассмотрите возможность убийства длительного активного сеанса транзакций, который задерживает очистку PVS.
- Настройте длительно выполняющиеся запросы, чтобы уменьшить время их выполнения.
- Просмотрите приложение, чтобы определить характер проблемного активного сканирования моментальных снимков. Рассмотрим другой уровень изоляции, например
READ COMMITTED
, вместоSNAPSHOT
или RCSI для длительных запросов, которые задерживают очистку PVS. Эта проблема часто возникает с уровнем изоляцииSNAPSHOT
. - В эластичных пулах базы данных SQL Azure рассмотрите возможность перемещения баз данных с длительными транзакциями с помощью изоляции
SNAPSHOT
или RCSI из эластичного пула.
Проверка запросов, выполняющихся долго, на вторичных репликах
Если база данных имеет вторичные реплики, проверьте, обновляется ли вторичная нижняя контрольная точка.
Выполните указанные динамические административные представления на первичной реплике, чтобы определить запросы с долгим временем выполнения на вторичной реплике, которые могут препятствовать очистке PVS.
- sys.dm_hadr_database_replica_states для SQL Server и управляемого экземпляра Azure SQL
-
sys.dm_database_replica_states (для базы данных SQL Azure и базы данных SQL в Microsoft Fabric) в столбце
low_water_mark_for_ghosts
.
В sys.dm_tran_persistent_version_store_stats dmV столбцы pvs_off_row_page_skipped_low_water_mark
также могут указывать задержку очистки из-за длительного запроса на вторичную реплику.
Подключитесь ко вторичной реплике, найдите сеанс, выполняющий длинный запрос, и рассмотрите возможность завершения сеанса, если это разрешено. Длительный запрос на вторичной реплике может задерживать очистку PVS и предотвращать очистку призраков .
Проверка большого количества прерванных транзакций
Если ни один из предыдущих сценариев не применяется к рабочим нагрузкам, скорее всего, очистка проводится из-за большого количества прерванных транзакций. Проверьте столбцы aborted_version_cleaner_last_start_time
и aborted_version_cleaner_last_end_time
, чтобы узнать, завершена ли последняя прерванная очистка транзакций. После очистки аварийно завершенных транзакций значение oldest_aborted_transaction_id
должно быть больше. Если oldest_aborted_transaction_id
гораздо ниже oldest_active_transaction_id
, а current_abort_transaction_count
имеет большее значение, скорее всего, старая прерванная транзакция предотвращает очистку PVS.
Чтобы устранить большое количество прерванных транзакций, рассмотрите следующее:
- Если это возможно, остановите рабочую нагрузку, чтобы позволить более чистой версии добиться прогресса.
- Оптимизируйте рабочую нагрузку для уменьшения блокировок на уровне объектов.
- Просмотрите приложение, чтобы определить проблему с высокой скоростью прерывания транзакций. Прерывания могут возникать из высокой частоты взаимоблокировок, повторяющихся ключей, нарушений ограничений или времени ожидания запроса.
- Если используется SQL Server, отключите ADR как экстренную меру для управления размером PVS. См. Отключение ADR.
- Если очистка прерванной транзакции недавно не завершилась успешно, следует проверить журнал ошибок на предмет наличия сообщений, сообщающих о проблемах
VersionCleaner
. - Если размер PVS не уменьшается, как ожидалось даже после завершения очистки, проверьте столбец
pvs_off_row_page_skipped_oldest_aborted_xdesid
. Большие значения указывают, что пространство по-прежнему используется версиями строк из прерванных транзакций.
Запуск процесса очистки PVS вручную
Если у вас есть рабочая нагрузка с большим количеством инструкций DML (INSERT
, UPDATE
, DELETE
, MERGE
), например, с высоким объемом OLTP, может потребоваться некоторое время простоя или восстановления, чтобы процесс очистки PVS мог вернуть пространство.
Для активации процесса очистки PVS вручную между рабочими нагрузками или периодами обслуживания используйте системную хранимую процедуру sys.sp_persistent_version_cleanup.
Например:
EXEC sys.sp_persistent_version_cleanup [WideWorldImporters];
Сбои очистки записи
Начиная с SQL Server 2022 (16.x), поведение очистки PVS записывается в журнал ошибок. Обычно это приводит к тому, что новое событие журнала записывается каждые 10 минут. Статистика очистки также сообщается расширенным событием tx_mtvc2_sweep_stats
.