6.12.25

Что такое ожидания LOGMGR_RESERVE_APPEND?

Автор: Paul Randal, What are LOGMGR_RESERVE_APPEND waits?

Мне прислали вопрос по электронной почте о причине возникновения ожиданий LOGMGR_RESERVE_APPEND, и в следующем выпуске рассылки Insider я дал краткое объяснение. Это очень необычный тип ожидания, чтобы видеть его в качестве основного на сервере, и, по сути, его вообще редко встречают.

Он возникает, когда поток создаёт запись журнала и ему нужно записать её в блок журнала, но в журнале нет для этого места. Сначала поток пытается увеличить размер журнала, и если это не удаётся, а база данных находится в режиме простого восстановления, то он ожидает 1 секунду, чтобы посмотреть, не произойдёт ли за это время очистка/усечение журнала, которое освободит место. (Отмечу, что когда я говорю «режим восстановления simple», это также включает базу данных в режимах full или bulk_logged, но где полная резервная копия ещё не делалась — то есть база данных работает в так называемом псевдопростом режиме).

Именно тот факт, что база данных должна находиться в режиме простого восстановления и в ней не должно быть доступного места, делает этот тип ожидания очень редким.

Пример стека вызовов для SQL Server 2014 (записанного с использованием этого механизма):

SOS_Task::PostWait+9e
SOS_Task::Sleep+149
SQLServerLogMgr::ReserveAndAppend+2cf
XdesRMReadWrite::GenerateLogRec+615
PageRef::InsertRows+2594
HeapPageRef::Insert+45a
HeapFragment::Update+3f7
HeapDataSetSession::InsertRowInternal+3444
DatasetSession::InsertRow+163
RowsetNewSS::InsertRow+26
CValRow::SetDataX+5b
CEsExec::GeneralEval4+e7
CQScanUpdateNew::GetRow+43d
CQueryScan::GetRow+81
CXStmtQuery::ErsqExecuteQuery+36d
CXStmtDML::XretDMLExecute+31c
CXStmtDML::XretExecute+ad
CMsqlExecContext::ExecuteStmts<1,1>+427
CMsqlExecContext::FExecute+a43
CSQLSource::Execute+86c

Вот сценарий, который демонстрирует его возникновение. Сначала я создам базу данных с журналом фиксированного размера, установлю для неё режим простого восстановления и создам таблицу, операции вставки в которую будут генерировать большие записи журнала:

CREATE DATABASE [Company] ON PRIMARY (
    NAME = N'Company_data',
    FILENAME = N'D:\SQLskills\Company_data.mdf')
LOG ON (
    NAME = N'Company_log',
    FILENAME = N'C:\SQLskills\Company_log.ldf',
    SIZE = 2MB,
    FILEGROWTH = 0MB);
GO
USE [Company];
GO
ALTER DATABASE [Company] SET RECOVERY SIMPLE;
GO
CREATE TABLE [BigRows] ([c1] INT IDENTITY, [c2] CHAR (8000) DEFAULT 'a');
GO

А затем в двух других окнах выполню следующий код:

USE [Company];
GO
SET NOCOUNT ON;
GO

WHILE (1 = 1)
BEGIN
    INSERT INTO [BigRows] DEFAULT VALUES;
END;
GO

И в течение нескольких секунд вы увидите, что возникают ожидания LOGMGR_RESERVE_APPEND (с помощью моего скрипта по ожиданиям). Вот пример (несколько столбцов удалено для краткости):

WaitType                       WaitCount Percentage AvgWait_S AvgRes_S AvgSig_S Help/Info URL
------------------------------ --------- ---------- --------- -------- -------- -------------------------------------------------------------------
LOGMGR_RESERVE_APPEND          26        50.78      0.9847    0.9847   0.0000   https://www.sqlskills.com/help/waits/LOGMGR_RESERVE_APPEND
PREEMPTIVE_OS_FLUSHFILEBUFFERS 954       22.14      0.0116    0.0116   0.0000   https://www.sqlskills.com/help/waits/PREEMPTIVE_OS_FLUSHFILEBUFFERS
WRITELOG                       131625    21.63      0.0001    0.0001   0.0000   https://www.sqlskills.com/help/waits/WRITELOG
PAGEIOLATCH_UP                 5841      3.37       0.0003    0.0003   0.0000   https://www.sqlskills.com/help/waits/PAGEIOLATCH_UP

Таким образом, если вы когда-нибудь увидите эти ожидания, ищите базы данных, использующие режим простого восстановления, у которых для журнала установлен нулевой или очень маленький автоматический рост.




Комментариев нет:

Отправить комментарий