28.10.26

Кто поменял MAXDOP 1 на экземпляре?

Автор: Paul Randal, Who is overriding MAXDOP 1 on the instance?

Мне пришёл вопрос по электронной почте: «как могут возникать ожидания латча ACCESS_METHODS_DATASET_PARENT, когда MAXDOP экземпляра установлен в 1?» Этого не должно происходить, так как эта краткая блокировка используется только для координации между потоками, выполняющими параллельное сканирование таблицы или индекса. Однако то, что MAXDOP экземпляра установлен в 1, не означает, что параллелизм не может возникнуть.

Любой может переопределить настройку MAXDOP экземпляра с помощью подсказки запроса.

Есть два способа предотвратить это:

  1. Установить настройку порога стоимости для параллелизма на экземпляре очень высокой, чтобы ни один последовательный план не мог быть признан достаточно дорогим для параллельного выполнения
  2. Заставить всех работать в группе нагрузки Resource Governor (только Enterprise Edition [Правка 2/4/26: в Standard Edition начиная с SQL Server 2025]) с установленным MAX_DOP в 1

Или вы можете выяснить, где используется подсказка запроса, и удалить её.

В этой статье я покажу вам простой сеанс Extended Events, который захватит информацию о том, что вызывает ожидания CXPACKET (ожидания латча ACCESS_METHOD_DATASET_PARENT не могут возникать без одновременных ожиданий CXPACKET), а затем уточню его, чтобы использовать менее дорогое событие.

Сначала я установлю свой MAXDOP в 1:

EXEC sp_configure 'show advanced options', 1; RECONFIGURE WITH OVERRIDE; GO EXEC sp_configure 'max degree of parallelism', 1; RECONFIGURE WITH OVERRIDE; GO SELECT [name], [value_in_use] FROM sys.configurations WHERE [name] LIKE '%degree%'; GO
Configuration option 'show advanced options' changed from 0 to 1. Run the RECONFIGURE statement to install.
Configuration option 'max degree of parallelism' changed from 0 to 1. Run the RECONFIGURE statement to install.
name                       value_in_use
-------------------------- -------------
max degree of parallelism  1

Затем я проверю наличие ожиданий CXPACKET (используя мой запрос по ожиданиям) после выполнения следующего запроса, который сканирует таблицу в 6,7 миллиона строк (базу данных SalesDB можно взять здесь):

SELECT * FROM [SalesDB].[dbo].[Sales] WHERE [Quantity] > 10000; GO

Ожиданий CXPACKET нет.

Но если я добавлю подсказку запроса MAXDOP и затем проверю ожидания:

SELECT * FROM [SalesDB].[dbo].[Sales] WHERE [Quantity] > 10000 OPTION (MAXDOP 8); GO
WaitType Wait_S Resource_S Signal_S WaitCount Percentage AvgWait_S AvgRes_S AvgSig_S Help/Info URL
LATCH_EX 0.20 0.16 0.05 93 79.61 0.0022 0.0017 0.0005 https://www.sqlskills.com/help/waits/LATCH_EX
CXPACKET 0.05 0.05 0.00 16 20.00 0.0032 0.0032 0.0000 https://www.sqlskills.com/help/waits/CXPACKET

И MAXDOP экземпляра был успешно проигнорирован и переопределён.

Теперь я настрою простой сеанс Extended Events, чтобы отследить offending-код (на основе запроса отсюда). Очень важно запросить DMV sys.dm_xe_map_values, чтобы найти правильное число для использования в запросе для ожидания CXPACKET, так как эти числа часто меняются от выпуска к выпуску и даже в пакетах обновления. Например, CXPACKET был 191 в SQL Server 2014 RTM, но 190 в сборке 2014, которую я использую.

Будьте очень осторожны при запуске этого в продакшене, так как событие будет срабатывать при каждом возникающем ожидании и, вероятно, повлияет на пропускную способность вашей рабочей нагрузки, даже если оно замкнётся, если ожидание не CXPACKET. Ниже я покажу вам лучшее событие для использования.

IF EXISTS ( SELECT * FROM sys.server_event_sessions WHERE [name] = N'InvestigateWaits') DROP EVENT SESSION [InvestigateWaits] ON SERVER GO CREATE EVENT SESSION [InvestigateWaits] ON SERVER ADD EVENT [sqlos].[wait_info] ( ACTION ( sqlserver.client_hostname, sqlserver.nt_username, sqlserver.sql_text) WHERE [wait_type] = 190 -- только CXPACKET AND [opcode] = 1 -- только события окончания ожидания ) ADD TARGET [package0].[ring_buffer] WITH ( MAX_MEMORY = 50 MB, MAX_DISPATCH_LATENCY = 5 SECONDS) GO ALTER EVENT SESSION [InvestigateWaits] ON SERVER STATE = START; GO

И затем, когда я снова выполняю оператор select, я могу посмотреть в кольцевой буфер и увидеть события. Я добавил DISTINCT, чтобы минимизировать количество строк вывода. Код:

SELECT DISTINCT ([data1].[value] ('(./@timestamp)[1]', 'datetime')) AS [Time], [data1].[value] ('(./action[@name="client_hostname"]/value)[1]', 'VARCHAR(MAX)') AS [Host], [data1].[value] ('(./action[@name="nt_username"]/value)[1]', 'VARCHAR(MAX)') AS [User], [data1].[value] ('(./action[@name="sql_text"]/value)[1]','VARCHAR(MAX)') AS [Statement] FROM ( SELECT CONVERT (XML, [target_data]) AS data FROM sys.dm_xe_session_targets [xst] INNER JOIN sys.dm_xe_sessions [xs] ON [xst].[event_session_address] = [xs].[address] WHERE [xs].[name] = N'InvestigateWaits') AS t CROSS APPLY data.nodes('//event') n (data1); GO
Time Host User Statement
2017-02-16 00:20:16.937 APPLECROSS APPLECROSS\Paul SELECT * FROM [SalesDB].[dbo].[Sales] WHERE [Quantity] > 10000 OPTION (MAXDOP 8);
2017-02-16 00:20:16.987 APPLECROSS APPLECROSS\Paul SELECT * FROM [SalesDB].[dbo].[Sales] WHERE [Quantity] > 10000 OPTION (MAXDOP 8);
2017-02-16 00:20:16.937 APPLECROSS SELECT * FROM [SalesDB].[dbo].[Sales] WHERE [Quantity] > 10000 OPTION (MAXDOP 8);

Здорово — так что это работает, но сеанс, вероятно, повлияет на производительность рабочей нагрузки, как я упоминал выше. Лучшее событие для использования — degree_of_parallelism, которое было введено в SQL Server 2012 и срабатывает только один раз на выполнение пакета, а не один раз на каждое возникающее ожидание.

Обновлённый сеанс событий:

CREATE EVENT SESSION [InvestigateWaits] ON SERVER ADD EVENT [sqlserver].[degree_of_parallelism] ( ACTION ( sqlserver.client_hostname, sqlserver.nt_username, sqlserver.sql_text) WHERE [dop] > 1 -- параллельные планы ) ADD TARGET [package0].[ring_buffer] WITH ( MAX_MEMORY = 50 MB, MAX_DISPATCH_LATENCY = 5 SECONDS) GO

И код для разбора XML, и пример вывода из моего запроса:

SELECT [data1].[value] ('(./@timestamp)[1]', 'datetime') AS [Time], [data1].[value] ('(./data[@name="dop"]/value)[1]', 'INT') AS [DOP], [data1].[value] ('(./action[@name="client_hostname"]/value)[1]', 'VARCHAR(MAX)') AS [Host], [data1].[value] ('(./action[@name="nt_username"]/value)[1]', 'VARCHAR(MAX)') AS [User], [data1].[value] ('(./action[@name="sql_text"]/value)[1]','VARCHAR(MAX)') AS [Statement] FROM ( SELECT CONVERT (XML, [target_data]) AS data FROM sys.dm_xe_session_targets [xst] INNER JOIN sys.dm_xe_sessions [xs] ON [xst].[event_session_address] = [xs].[address] WHERE [xs].[name] = N'InvestigateWaits') AS t CROSS APPLY data.nodes('//event') n (data1); GO
Time DOP Host User Statement
2017-02-16 00:36:37.347 8 APPLECROSS APPLECROSS\Paul SELECT * FROM [SalesDB].[dbo].[Sales] WHERE [Quantity] > 10000 OPTION (MAXDOP 8);

Довольно круто, а?

Вы можете возиться с более сложным кодом, который делает такие вещи, как захват действия tsql_stack и затем его разбор, и больше информации для идентификации виновника, например, имени приложения — насколько сложно вы захотите — но теперь вы знаете базовый сеанс событий для захвата, когда используется подсказка запроса.




27.10.26

Некролог на ночное задание по перестроению индексов, 1998–2026

Автор: Pinal Dave, The Nightly Index Rebuild Job, 1998 to 2026: An Obituary

Ночное задание по перестроению индексов скончалось после долгой болезни. Оно родилось в 1998 году для жёсткого диска, который не умел эффективно перемещать головки для поиска. Оно так и не поверило, что диск заменили. Его пережила плотность страниц, которая, как выяснилось, всё это время выполняла основную часть его работы. Это было задание по привычке. Каждую ночь в два часа, независимо от того, изменилось ли что-нибудь, оно перестраивало каждый индекс в базе данных. Каждое утро база данных была ровно такой же быстрой, как и прошлой ночью. Никто не помнит, кто его запланировал. Все помнят, что им говорили его не убирать.

26.10.26

Накопительный пакет обновления SQL Server 2025 CU10 - KB5125471

Описание: KB5125471

Скачать: SQLServer2025-KB5125471-x64.exe

Дата выпуска: 22 октября 2026 г.

SQL Server 2025 — Версия: 17.0.5035.5

Analysis Services — Версия: 17.0.25.223

~40 фиксов в одном обновлении, главное:

🔒 Безопасность (критично)

  • Уязвимости в VDI (Backup/Restore) — выход за границы памяти
  • RCE и утечки в PolyBase и ML Services (SQLSatellite)
  • Повышение привилегий через метаданные бэкапа
  • Множество дыр в Replication (включая Log Reader Agent и sp_replcounters)

⚙️ Движок

  • Порча XML при сжатии (off-row)
  • Падение при JSON-индексах с Unicode >8000 байт
  • OOB-чтение в SQL Trace (LoginSid)
  • Утечки памяти в AI_GENERATE_EMBEDDINGS и SqlDataRecord.SetBytes

🐧 Linux

  • Ошибка 1803 при создании contained AG после смены collation

🔄 Репликация и CES

  • Buffer overflow в merge replication (>250 XML-ников)
  • Падения при сериализации в Change Event Streaming

🔗 Прочее

  • Сбой linked server (MSDASQL) без UID
  • Валидация Delta Lake и FILESTREAM на вторичных репликах

Окончание поддержки SQL Server 2016: как выбрать путь обновления

Автор: Greg Low, SQL Server 2016 end of support: how to choose your upgrade path

SQL Server 2016 достиг окончания расширенной поддержки в июле 2026 года, что означает, что он больше не получает регулярных обновлений безопасности, если вы не платите за расширенные обновления безопасности (ESU). Ваши реалистичные варианты — обновиться до SQL Server 2025, обновиться до SQL Server 2022 или купить ESU на срок до трёх дополнительных лет (до июля 2029 года), независимо от того, запускаете ли вы SQL Server локально или в Microsoft Azure. Для большинства производственных систем я рекомендую параллельную миграцию на SQL Server 2025, если только поставщик приложения или удалённый из последней версии функционал не исключают это. Правильный подход в конечном счёте зависит от совместимости приложений, ограничений инфраструктуры, допустимого простоя, затрат на лицензирование и того, как долго новая среда должна оставаться поддерживаемой.

В этой статье я рассмотрю ключевые решения (обновление на месте vs параллельная миграция, SQL Server 2022 vs SQL Server 2025, локально vs Microsoft Azure и ESU), а также контрольный список перед обновлением и советы по откату, чтобы снизить риск.

23.10.26

Поиск первопричины медленных запросов

Автор: Pinal Dave, Finding the Root Cause of Slow Queries

Поиск первопричины медленных запросов начинается с разделения работы и ожиданий, а затем проверки теорий на планах и истории. Вот вам пример показательного вторника. В 10:12 поиск заказа, который обычно возвращался за 180 миллисекунд, занял 14,8 секунды. Сорок три сеанса накопились за пять минут, и команда приложения захотела новый индекс ещё до обеда. CPU оставался скромным, логические чтения оставались привычными, а кэшированный план совпадал со вчерашним быстрым планом. Запрос провёл почти всю свою жизнь в ожидании LCK_M_S. Ночной процесс инвентаризации оставил открытой транзакцию обновления. Видимый запрос был жертвой, а не виновником. Команда проследовала по blocking_session_id, пока цепочка не закончилась на спящем сеансе. Его последний пакет показывал обновление инвентаризации, и данные транзакции подтвердили незафиксированную работу. Как только этот владелец безопасно зафиксировал транзакцию, задержка упала ниже 200 миллисекунд. Никто не редактировал код жертвы, индексы или статистику.

21.10.26

Как зашифровать бэкапы и не поседеть при восстановлении

Тема внезапно стала мейнстримом: в датацентры иногда прилетает, и тогда очень хочется иметь копию не «где-то там», а на альтернативной площадке. И чтобы её никто не прочитал. Погнали.

20.10.26

Взаимоблокировка SQL Server: создайте её сами

Автор: Pinal Dave, SQL Server Deadlock: Build One With Your Own Hands

Взаимоблокировка SQL Server возникает, когда сеансы образуют цикл зависимостей и ни один не может продолжить, тупиковая ситуация. Этот пример позволяет вам создать цикл, изучить его и устранить.

Transaction (Process ID 57) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

SQL Server разрешает цикл, выбирая одну транзакцию в качестве жертвы, откатывая её и возвращая ошибку 1205. Выжившая транзакция затем может продолжить.

19.10.26

Очистка установки SQL Server с помощью UninstallString, когда запись в «Программах и компонентах» отсутствует

Автор: Vivek Janakiraman, SQL Server Cleanup Using UninstallString When Programs and Features Entry is Missing

Иногда случается, что службы SQL Server могут по-прежнему существовать на сервере, но связанные записи SQL Server отсутствуют в «Программах и компонентах». Это может происходить из-за отсутствующих или повреждённых записей реестра, неполного удаления или неудачных действий по установке исправлений.

Исправление безопасности для SQL Server 2025 CU9 - KB5126967

Описание: KB5126967

Скачать: SQLServer2025-KB5126967-x64.exe

Дата выпуска: 13 октября 2026 г.

SQL Server 2025 — Версия: 17.0.5015.4

Краткий перечень исправлений:

  • PolyBase: усилена проверка данных, устранены падения при работе с внешними источниками, добавлена валидация схемы delta-таблиц, исправлена небезопасная десериализация очереди отката, обновлена обработка разделяемой памяти. 
  • Backup Restore (VDI): устранены переполнения буфера и выходы за границы памяти при открытии виртуальных устройств и обработке данных; ужесточена проверка размеров и границ. 
  • Extended Events: устранены уязвимости раскрытия информации и отказа в обслуживании при чтении специально сформированных файлов .xel. 
  • Extensibility: обновлён сторонний компонент распаковки архивов; исправлено небезопасное чтение памяти в параметрах AI_GENERATE_EMBEDDINGS; устранены повреждения и раскрытие памяти в парсинге протокола SQL Satellite. 
  • Replication: повышена безопасность и надёжность очередей обновляемых подписок, метаданных безопасности, Log Reader Agent, change feed и потоковой передачи событий; исправлено переполнение буфера при >250 записей 
  • WebSync; усилены проверки авторизации; исправлены проблемы валидации данных. 
  • High Availability: добавлена проверка размера фрагментов FILESTREAM на вторичных репликах. 
  • Query Store: улучшена обработка входных данных Showplan. 
  • Distributed Query: исправлен сбой подключений через MSDASQL при отсутствии UID в строке провайдера. 
  • SQL Trace: ограничена обработка LoginSid размером внутреннего буфера для предотвращения выхода за границы.

Исправление безопасности для SQL Server 2025 GDR - KB5128492

Описание: KB5128492

Скачать: SQLServer2025-KB5128492-x64.exe

Дата выпуска: 13 октября 2026 г.

SQL Server 2022 — Версия: 17.0.1145.4

Краткий перечень исправлений:

  • PolyBase: усилена проверка данных, устранены падения при работе с внешними источниками, добавлена валидация схемы delta-таблиц, исправлена небезопасная десериализация очереди отката, обновлена обработка разделяемой памяти. 
  • Backup Restore (VDI): устранены переполнения буфера и выходы за границы памяти при открытии виртуальных устройств и обработке данных; ужесточена проверка размеров и границ. 
  • Extended Events: устранены уязвимости раскрытия информации и отказа в обслуживании при чтении специально сформированных файлов .xel. 
  • Extensibility: обновлён сторонний компонент распаковки архивов; исправлено небезопасное чтение памяти в параметрах AI_GENERATE_EMBEDDINGS; устранены повреждения и раскрытие памяти в парсинге протокола SQL Satellite. 
  • Replication: повышена безопасность и надёжность очередей обновляемых подписок, метаданных безопасности, Log Reader Agent, change feed и потоковой передачи событий; исправлено переполнение буфера при >250 записей 
  • WebSync; усилены проверки авторизации; исправлены проблемы валидации данных. 
  • High Availability: добавлена проверка размера фрагментов FILESTREAM на вторичных репликах. 
  • Query Store: улучшена обработка входных данных Showplan. 
  • Distributed Query: исправлен сбой подключений через MSDASQL при отсутствии UID в строке провайдера. 
  • SQL Trace: ограничена обработка LoginSid размером внутреннего буфера для предотвращения выхода за границы.

Исправление безопасности для SQL Server 2022 CU27 - KB5126934

Описание: KB5126934

Скачать: SQLServer2022-KB5126934-x64.exe

Дата выпуска: 13 октября 2026 г.

SQL Server 2022 — Версия: 16.0.4305.5

Исправление безопасности для SQL Server 2022 GDR - KB5128493

Описание: KB5128493

Скачать: SQLServer2022-KB5128493-x64.exe

Дата выпуска: 13 октября 2026 г.

SQL Server 2022 — Версия: 16.0.1210.3