Що станеться, коли для SQL Server не залишилося вільної фізичної пам'яті?


16

Під час гугла я знайшов суперечливу інформацію.

Деякі сайти заявляють, що коли для даних не залишається фізичної пам'яті, SQL Server переміщує вже наявні дані в TEMPDB (див.: SQL Server: Демістифікація TempDb та рекомендації ).

Але інші сайти стверджують, що, коли не вистачає фізичної пам’яті, операційна система може використовувати PAGE FILE і переміщувати дані з фізичної пам’яті до неї (див. Сторінку файлів для SQL Server ).

Цікаво, куди SQL Server записує дані, коли у нього закінчується фізична пам'ять? У tempdb або у файл сторінки ОС? А може, обох?

Відповіді:


28

коли для даних не залишилося фізичної пам'яті, SQL Server переміщує вже наявні дані в TEMPDB

Стаття, з якою ви пов’язані, в кращому випадку вводить в оману, а в деяких місцях неправильна. Я думаю, що автор намагався надто спростити деякі складні речі, і при цьому пішов трохи надто далеко.

Таким чином, SQL Server не переміщує дані з пам'яті (буферний пул) у tempdb. У ній використовується стратегія кешування "найменше використаної" (загалом), тому якщо є тиск в пам'яті, і нові дані потрібно витягнути в пам'ять, SQL Server виведе дані LRU з буферного пулу для розміщення нових даних. Ця поведінка часто контролюється лічильником парфмонів під назвою "Тривалість життя сторінки" (PLE) :

Визначення PLE - це очікуваний час у секундах, коли сторінка файлу даних, прочитана в буферному пулі (кеш пам'яті сторінок файлів даних), залишиться в пам'яті, перш ніж виштовхуватися з пам'яті, щоб звільнити місце для інших даних сторінка файлу. Ще один спосіб думати про PLE - це миттєва міра тиску на буферний пул, щоб звільнити місце для читання сторінок з диска. В обох цих визначеннях більша кількість кращих.

Під час виконання запитів SQL Server може використовувати tempdb для певних операцій. Зазвичай це робиться, якщо оцінки погані, але низька доступна пам'ять може вплинути на таку поведінку.

Деякі з операцій, які можуть "розпливатися" до tempdb таким чином, - це хешування рядків (для об'єднань чи агрегатів тощо), сортування рядків у пам'яті та буферизація рядків під час паралельного виконання запитів.

Запити користувачів також можуть явно використовувати tempdb (із загальними або локальними тимчасовими таблицями), а також неявно використовувати tempdb (із знімком або зчитуванням рівнів ізоляції знімків, що виконуються).

Жодна з цих ситуацій насправді не відповідає заяві, яку ви цитували.

коли у вас не вистачає фізичної пам'яті, операційна система може використовувати СТАРТІЙНИЙ ФАЙЛ і переміщувати дані з фізичної пам'яті до нього

Це однозначно може статися, і здебільшого вона знаходиться поза контролем SQL Server. Існує ручка, яку можна повернути, щоб спробувати запобігти деяким типам підкачки на рівні ОС, а саме ввімкнути "Заблокувати сторінки в пам'яті" (LPIM) :

Ця політика Windows визначає, які облікові записи можуть використовувати процес для збереження даних у фізичній пам'яті, не даючи системі передати дані на віртуальну пам'ять на диску.

То що ж ми можемо не допустити, щоб перейти на сторінку на диску?

До початку SQL Server 2012 сторінки, які були виділені через компонент під назвою "Розподіл єдиної сторінки", були заблоковані в пам'яті (не можна було підключити до сторінки). Сюди входили пул буфера (сторінки бази даних), кеш процедур та деякі інші області пам'яті.

Докладні відомості див. У розділі Весело із заблокованими сторінками, AWE, диспетчером завдань та робочим набором ... , особливо розділ "4. Тепер я знаю, що SQL Server на x64 може використовувати" Заблоковані сторінки ", що саме заблоковано?" Тут можна ознайомитись із додатковими читаннями: Великі дебати на SQL сервері: Сторінки блокування в пам'яті

У SQL Server 2012 та пізніших версіях не існує "Розподільника однієї сторінки" (однорозподільник та багатосторінковий розподільник об'єднали відповідно до Поглибленого погляду на пам'ять - SQL Server 2012/2014 ). Деталі того, що саме можна, а що неможливо прописати на сторінці, детально не задокументовано ніде, що я бачив. Ви можете використовувати запит , як це , щоб побачити , що буде закритий

select osn.node_id, osn.memory_node_id, osn.node_state_desc, omn.locked_page_allocations_kb
from sys.dm_os_memory_nodes omn
inner join sys.dm_os_nodes osn on (omn.memory_node_id = osn.memory_node_id)
where osn.node_state_desc <> 'ONLINE DAC'

Згідно з тією ж статтею про підтримку MS, ви також можете використовувати, DBCC MEMORYSTATUSщоб побачити, скільки пам'яті "заблоковано".

Як бічну примітку, ви можете бачити докази того, що робочий набір SQL Server підписується системою в журнал помилок. Будуть повідомлення, які виглядають приблизно так:

2019-09-02 10: 19: 27.29 spid11s Значна частина оперативної пам’яті серверного процесу вимкнена. Це може призвести до зниження продуктивності. Тривалість: 329 секунд. Робочий набір (КБ): 68780, прихильний (КБ): 244052, використання пам'яті: 28%.


0

Сучасні версії SQL-сервера мають дуже малий шанс зависнути взагалі. SQL Server завантажує .NET Framework у свій адресний простір і використовує його в звичайній роботі. Якщо фізична пам'ять та файл сторінки закінчуються, Windows спробує виростити файл сторінки; однак, навіть якщо він може збільшити файл сторінки, це не миттєва операція, і виділення пам'яті не вдається, поки файл сторінки зростає. В асинхронному обробнику вводу / виводу .NET є помилка, де він виділяє пам'ять у відповідь на повідомлення APC. Якщо дзвінок newне вдасться, він кинетьсяOutOfMemoryException. Цей виняток потрапляє в нативний код всередині планувальника завдань; однак асинхронний введення / виведення, здається, ніколи не закінчиться. Нитка фіналізатора для FileStream блокує очікування завершення вводу / виводу, щоб він міг відкрутити буфер, тим самим повісивши нитку фіналізатора назавжди. Це призводить до того, що .NET Framework поступово використовує все більше і більше пам’яті, поки не буде виділено більше пам’яті, і тоді SQL-сервер буде не реагувати, оскільки winsock не може виділяти більше буферів, тому навіть підключення до адміністратора є марним.

Я фактично потрапив у загальний запуск планувальника завдань у додатку .NET через нестачу пам'яті. На щастя, процес остаточно загинув через накидання OutOfMemoryExceptionна якусь нитку, яка не зачепила його після декількох відмов, щоб ми могли зрозуміти, що насправді зависає сервер.

Одного разу я зрозумів, що шукаю, знайти помилку в статичному аналізі було просто.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.