БД SQL Server стає непридатним протягом ночі


9

Вчора моя база даних SQL Server була в порядку. Сьогодні це майже непридатне використання - уповільнюється на коефіцієнт від п'яти до двадцяти, залежно від того, коли я потрапив у нього.

Деякі дані були додані на сервер під час завантаження за ніч, але нічого подібного до обсягу, який би настільки вплинув на базу даних. Близько 50 000 записів із звичайним текстом (без XML чи інших криптовалют).

Сервер був виправлений сьогодні вранці, перш ніж ми його перезавантажили. Однак жоден з інших наших серверів баз даних, які також отримали виправлення, не веде себе по-різному.

Монітор ресурсів, здається, дозволяє припустити, що його диск IO, що винен. Він працює на майже 100% ємності у файлі .mdf весь час, навіть коли насправді в базі даних не відбувається багато. Доступ до Templog.ldf також працює досить високо.

Ніхто тут не є експертом DBA (ми всі розробники з різною кількістю навичок SQL), і нас усіх бентежить те, що сталося. Ми спробували запустити sp_updatestats і перемістити деякі великі індекси на різні диски, безрезультатно.

Я думаю, що це повинно мати щось спільне з виправленням - це здається занадто великим випадковим випадком. Колега впевнений, що саме завантаження даних призвело до того, що розмір mdf збільшився до моменту, коли це спричинило неефективність виконання планів.

Що на землі це спричинило? Як ми можемо це дізнатись, і що ми можемо зробити, щоб виправити це?

Редагувати:

Використання sp_WhoIsActiveвиявляє нічого незвичайного. Він реєструє моє власне використання відростка та деякі команди від колеги, який наразі намагається перемістити інший індекс. Це, мабуть, затримка БД прямо зараз, але вона працювала так само погано.

Це стандартна версія SQL Server 2008 R2. SELECT @@VERSIONдає:

Microsoft SQL Server 2008 R2 (SP2) - 10.50.4033.0 (X64)
9 липня 2014 16:04:25
Авторські права (c) Стандартна версія Microsoft Corporation (64-розрядна) для Windows NT 6.1 (Build 7601: Service Pack 1) (Hypervisor )

Сервер має 72 Гб оперативної пам’яті та три чотириядерні 2 ГГц процесори.

Виправлення застосовано лише для Windows. Не було змін, крім патчу.

Вибрані налаштування:

_id     name                        value   minimum     maximum     value_in_use    description                                 is_dynamic  is_advanced
1540    min memory per query (KB)   1024    512         2147483647  1024            minimum memory per query (kBytes)           1           1
1541    query wait (s)              -1      -1          2147483647  -1              maximum time to wait for query memory (s)   1           1
1543    min server memory (MB)      0       0           2147483647  16              Minimum size of server memory (MB)          1           1
1544    max server memory (MB)      65536   16          2147483647  65536           Maximum size of server memory (MB)          1           1

ОНОВЛЕННЯ: Переміщення індексів та таблиць на різні дискові розділи, схоже, покращує ситуацію. Я все ще розгублений, як ми могли так раптово досягти переломної точки з такими різкими результатами.


Чи можете ви запустити sp_whoisactive протягом 5 хв і зафіксувати висновок до таблиці. Ви можете завантажити його звідси, і це покаже, як ви можете зафіксувати вихідну таблицю
Кін Шах

Добре, якщо ви перезапустили сервер, це означає, що всі ваші кешовані дані були скинуті з буферного пулу, а також всі ваші плани кешованого виконання також були скинуті. Це означає, що SQL Server повинен буде нарощувати обоє - кожен план виконання повинен бути перекомпільований, і якщо статистика застаріла, можливо, ви не отримаєте найефективніші плани. Це також означає, що дані доведеться зчитувати з пам'яті з диска, тоді як перед перезапуском він, ймовірно, гудів разом із даними в пам'яті. Це повинно бути короткочасним.
Аарон Бертран

@AaronBertrand Це було вісім годин. Ми регулярно перезавантажуємо сервер для виправлення і ніколи не помічали нічого подібного раніше.
Боб Твей

1
Не використовуйте інтерфейс користувача, щоб перевірити настройки конфігурації. SELECT * FROM sys.configurations;- ти хочеш value, value_in_useза такі речі max server memory (MB). Також SELECT @@VERSION;було б корисно число збірки в , а також, чи є це в гіпервізорі та чи щось змінилося на хості з вчорашнього дня (або з моменту останнього перезапуску SQL Server).
Аарон Бертран

2
Який тип підсистеми вводу-виводу ви використовуєте? SAN, локальний диск тощо? Чи є шанс, що у вас випадково поганий привід? Чи зберігаються будь-які ваші БД у тому самому місці, що і будь-які файли ОС? І останнє питання. Частиною нашого процесу перед оновленням ОС було попередньо зробити знімок VM. На жаль, відповідальна особа забула це зробити. Дуже швидко вся система стала повільнішою і повільнішою. Якийсь шанс це трапилося з вами?
Кеннет Фішер

Відповіді:


3

Може статися, що невелика кількість даних досягне певної межі в SQL Server, щоб змусити інший план або щось подібне. Це малоймовірно. Але той факт, що ваш диск, здається, сильно перебуває під обов'язком, підводить мене до іншого висновку.

Існує 2 можливих базових причини вашого сповільнення.

  1. Ви оновили систему та перезавантажили її
  2. Ви завантажуєте в неї купу даних

Давайте розглянемо частину №1

Можливо, ваша конфігурація SQL Server може бути порушена. Це може спричинити серйозні проблеми щодо швидкості вашого сервера та використання диска.

Перевірте в першу чергу основні настройки сервера. Ці основні параметри max server memory, affinity I/O mask, affinity maskі max degree of parallelism. Можливо, вам потрібно буде включити розширені параметри, використовуючи show advanced options.

Ось повний сценарій:

-- enable advanced options
EXEC sp_configure 'show advanced options',1
-- apply configuration
RECONFIGURE
-- how much memory can the sql server allocate?
EXEC sp_configure 'max server memory'
-- which cpu is used to run I/O operations
EXEC sp_configure 'affinity I/O mask'
-- which cpus can run processes?
EXEC sp_configure 'affinity mask'
-- how many threads can work on one query part?
EXEC sp_configure 'max degree of parallelism'

Порівняйте результат із задокументованими значеннями на етапі встановлення. Вони все-таки однакові?

Це може бути багато причин, чому ваш сервер поводиться так дивно. Я б, як правило, робив ставку, що ви max server memoryпросто помиляєтесь. Це призведе до того, що ваш SQL Server буде постійно міняти сторінки даних. Він не може утримати все в своїй пам'яті. Це означає, що йому потрібно прочитати сторінки з диска, оновити його, миттєво записати його назад. Якщо з'являється інше оновлення, яке використовує ту саму сторінку для оновлення, воно не може бути прочитане з пам'яті. Натомість серверу потрібно знову прочитати його з диска. Просто поміняти ...

Іншою проблемою може бути висока спорідненість на диску чи процесах. Якщо ви використовували спільний сервер (SQL Server + інші служби) з виділеним диском для SQL Server (що може бути рідкісним випадком, але це може бути), це може бути вашою проблемою. Ваш сервер зазвичай мав, наприклад, 3 процесора для процесів і один для вводу / виводу. Інші 12 процесорів використовуються для інших послуг. У цьому випадку ваша маска спорідненості неправильна і використовує, наприклад, автоматичну конфігурацію. Це означає, що Ваш сервер динамічно використовує всі 16 ядер для процесів і вводу / виводу. Якщо у вас запущені величезні процеси, вони можуть поставити величезне навантаження на диск, який він може не впоратися. Але насправді я не вірю, що це ваш випадок. Це було б швидше (навіть якби трохи), якби це застосовувалося, але ваш випадок - це сповільнення.

Іншою проблемою може бути занадто високий ступінь паралелізму. Це означає, що у вас є занадто багато темпів на холостому ходу в одній частці запиту. Це також може спричинити величезне уповільнення, якщо паралелізм не буде працювати так, як очікувалося. Але це не описує ваш високий вхід / вивід усього.

Тепер давайте подивимось і на частину №2

Ви завантажуєте купу рядків у вашу систему. Навіть якщо це звичайна робота, це може підвищити межу, в якій ваші плани запитів ескалюватимуть. Можливо, навіть так, що ваша вставка в поєднанні з SQL Server викликає таку поведінку.

Ви згадали, що ви вже намагалися перенести свої індекси на інший диск, який, здається, допомагає. Це може статися лише тому, що ви розділили навантаження на два різні диски.

Можливо, ваші індекси були розбиті, ваші плани були розбиті або статистика застаріла.

1. дозволяє перевірити статистику останнього оновлення. Це можна зробити вручну через інтерфейс для кожного окремого елемента статистики. Що було б болем. Або ви можете спробувати цей код:

SELECT name AS indexname,
STATS_DATE(OBJECT_ID, index_id) AS StatsUpdated
FROM sys.indexes

Це дасть вам повну інформацію про кожен індекс (і купу) та статистику за ними. Навіть якщо ви запустили, sp_updatestatsце не означає, що статистика була оновлена. Частина, коли оновлення досить складне, навіть якщо ви запускаєте sp_updatestatsабо навіть якщо auto update statisticsвоно ввімкнено, статистика не буде оновлюватися вчасно. Ось кілька кращих моментів, коли потрібно / генерується оновлення:

  • Порожня таблиця отримує один або кілька рядків
  • Таблиця, що містить понад 500 рядків, оновлює 20% + 500 додаткових рядків, а вставка відбулася згодом
  • Коли було змінено 500 рядків у таблиці, що містить менше 500 рядків

Це означає, що ваша статистика може бути застарілою, навіть якщо ви запустите оновлення.

Ви можете подивитися на запит вище. Якщо ви знайдете досить стару статистику в деяких таблицях, ви можете запустити вручну оновлення статистики для цієї таблиці:

UPDATE STATISTICS dbo.YourBadTable WITH FULLSCAN

Після цього, можливо, ви захочете дати своєму серверу поштовх в дупу, щоб викинути всі старі плани.

DBCC FREEPROCCACHE 

Якщо ви просто хочете очистити всі кеші, ви можете запустити це:

DBCC FREESYSTEMCACHE ('ALL')

Це очистить усі кеші, а не лише кеш плану. Зазвичай я попереджую, використовувати це на виробничому сервері у фазі виробництва. Але оскільки ваш сервер зараз не працює, ви не можете їм завдати великої шкоди. Це може сповільнитися на кілька секунд, може, 1-2 хвилини, оскільки йому потрібно відновити всі кеші, але після цього він повинен працювати з правильними планами.

Ще однією причиною можуть бути повністю фрагментарні індекси. Це можна перевірити на всьому сервері за допомогою цього оператора:

SELECT * 
FROM sys.dm_db_index_physical_stats (NULL, NULL, NULL, NULL, NULL)

Якщо фрагментація дуже велика, можливо, вам доведеться реорганізувати (фрагментація <20%) або повністю відновити (> 20%) її. Це може зайняти більший тиск на ваш диск і призвести до неприємностей. З іншого боку, якщо показники будуть такими поганими, це, мабуть, допоможе врешті більше, ніж шкодить.

Крім цих двох причин, існує ще третя проблема

Можливо, ваш сервер налаштований, ймовірно, ви не змінили жодного коду за цей час, просто додали кілька рядків. Вся статистика оновлюється, а всі кеші відновлюються. Усі ваші індекси реорганізовані так, як вам потрібно, але все одно - нічого не працює. Можливо, ви досягли межі доступної пам'яті у своїх процесах. Можливо, вам потрібно більше. Ви можете просто перевірити, чи є якийсь процес, який намагається отримати більше пам'яті, ніж у вас.

Ви можете перевірити це за допомогою цієї команди:

SELECT * FROM sys.dm_exec_query_memory_grants

Він надасть вам список усіх сеансів, які вимагають пам'яті. Можливо, буде якийсь запит, який ще чекає, щоб отримати пам'ять. Ці запити можна легко відфільтрувати. Усі сесії де granted_memory_kb IS NULL. Це сеанси, які вимагають пам'яті, але не отримують її. Інша річ може бути наданою пам'яттю, яка може бути низькою. Ви можете порівняти стовпці requested_memory_kbз granted_memory_kb. Запрошений показує, скільки пам’яті потрібно для оптимального запуску процесу при наданні, відображається пам’ять, яка ввімкнена для процесу. Якщо для запуску процесу потрібно 2 Гб, але отримує лише 2 Мб ..., ви можете отримати його самостійно. ;-)

Ще один спосіб - перевірити RESSOURCE_SEMAPHORE:

SELECT * FROM sys.dm_exec_query_resource_semaphore

Ви можете подивитися на waiter_countта grantee_count. Якщо офіціант вище 0, ти тиснеш на пам’ять, що може спричинити заміну і може спричинити тиск на диску, який ти бачив у парфмоні.


0

Окрім можливих збоїв накопичувача, перевірте стан вашої підсистеми RAID. Ми побачили щось подібне, і виявилося, що батарея на RAID-контролері вийшла з ладу, тому не було доступного кешу запису - всі записи повинні були перейти безпосередньо на диск. Одне бокове зауваження - ми могли відчути паузу системи, коли RDC'ing в неї.

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