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

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