Що відбувається в контрольній точці PostgreSQL?


22

Ось частина мого журналу контрольних точок:

2014-03-26 11:51:29.341 CDT,,,18682,,532854fc.48fa,4985,,2014-03-18 09:15:24 CDT,,0,LOG,00000,"checkpoint complete: wrote 15047 buffers (1.4%); 0 transaction log file(s) added, 0 removed, 30 recycled; write=68.980 s, sync=1.542 s, total=70.548 s; sync files=925, longest=0.216 s, average=0.001 s",,,,,,,,,""
2014-03-26 11:56:05.430 CDT,,,18682,,532854fc.48fa,4987,,2014-03-18 09:15:24 CDT,,0,LOG,00000,"checkpoint complete: wrote 16774 buffers (1.6%); 0 transaction log file(s) added, 0 removed, 31 recycled; write=72.542 s, sync=17.164 s, total=89.733 s; sync files=885, longest=3.812 s, average=0.019 s",,,,,,,,,""
2014-03-26 12:01:21.650 CDT,,,18682,,532854fc.48fa,4989,,2014-03-18 09:15:24 CDT,,0,LOG,00000,"checkpoint complete: wrote 14436 buffers (1.4%); 0 transaction log file(s) added, 0 removed, 33 recycled; write=122.350 s, sync=5.212 s, total=127.676 s; sync files=924, longest=3.740 s, average=0.005 s",,,,,,,,,""
2014-03-26 12:06:25.028 CDT,,,18682,,532854fc.48fa,4991,,2014-03-18 09:15:24 CDT,,0,LOG,00000,"checkpoint complete: wrote 13277 buffers (1.3%); 0 transaction log file(s) added, 0 removed, 29 recycled; write=126.217 s, sync=5.733 s, total=131.991 s; sync files=894, longest=1.859 s, average=0.006 s",,,,,,,,,""
2014-03-26 12:10:41.958 CDT,,,18682,,532854fc.48fa,4993,,2014-03-18 09:15:24 CDT,,0,LOG,00000,"checkpoint complete: wrote 20765 buffers (2.0%); 0 transaction log file(s) added, 0 removed, 28 recycled; write=88.015 s, sync=10.818 s, total=98.872 s; sync files=881, longest=2.690 s, average=0.012 s",,,,,,,,,""

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

Питання: Чи міг цей пункт пропуску викликати це? Що відбувається на фазі «синхронізації» КПП?

Відповіді:


32

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

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

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

Цей змив відбувається в два етапи:

  • Буферизація write()S брудний shared_buffersдо таблиць; і
  • fsync() пошкоджених файлів, щоб переконатися, що зміни дійсно потрапили на диск

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

Це давнє завдання, але воно стає гіршим, оскільки ми бачимо системи з більшою кількістю оперативної пам'яті, щоб вони могли зберігати більше даних і забирати більше часу, щоб їх виписати. Наразі між спільнотами Linux та PostgreSQL існує дискусія щодо того, як впоратися з цим на даний момент, про що йдеться у цій статті на LWN.net . (LWN.net не зможе продовжувати писати таку велику роботу, якщо люди не підписуються. Я підписався і поділююсь цим посиланням, оскільки це корисно та інформативно. Будь ласка, розглянути підписку, якщо ви хочете побачити більше цього щось таке.)

Головне, що ви можете зробити, щоб зменшити вплив контрольно-пропускних пунктів на даний момент, - це поширити діяльність контрольно-пропускного пункту шляхом збільшення, checkpoint_completion_targetщоб більше часу було списано до моменту прибуття остаточного пункту пропуску. Це, однак, коштує - якщо ви оновлюєте сторінку (скажімо) десять разів, вона може бути записана на диск кілька разів перед контрольно-пропускною точкою з високою ціллю завершення, навіть якщо для безпеки аварій її потрібно було строго виписати один раз. Більш висока ціль виконання завершує плавніші схеми вводу / виводу, але загальні накладні витрати на введення / виведення.

Інша річ, яку ви можете зробити для того, щоб допомогти, - це сказати вашій операційній системі негайно почати записувати дані, коли вони отримують буферні записи. Це подібно до налаштування ядра checkpoint_completion_targetта має аналогічний компроміс. Дивіться документацію Vm Лінукс , зокрема dirty_background_bytes, dirty_background_ratio, dirty_expire_centisecs.


Запис розповсюджується протягом тривалого часу, і я не думаю, що це викликає проблеми. Як щодо синхронізації, чи це випадково операція зупинки у світі?
Конрад Гарус

@KonradGarus Синхронізація не повинна бути операцією зупинки у всьому світі, але часто все-таки є. Прочитайте статтю, до якої я посилався вище, це дуже своєчасний і корисний підсумок питань, хоча і з досить технічної точки зору. Коротка версія "fsync () в Linux має тенденцію повністю знищити продуктивність будь-якого вводу / виводу, який одночасно з fsync ()". Ви можете пом'якшити це за допомогою перелічених вище параметрів настройки, щоб зменшити суму, яку необхідно вимити за допомогою фсинсеку.
Крейг Рінгер

1

Промивання брудних буферів файлової системи ОС, викликаних перевищенням dirty_bytesабо dirty_ratio є операцією блокування переднього плану!

В ядрі параметрів настройки dirty_bytes, dirty_background_bytes, dirty_ratio, dirty_background_ratioі dirty_centisecsконтроль змив брудних файлової системи ОС буферів на диск. dirty_bytes- поріг у байтах, dirty_ratio- поріг як відношення загальної пам'яті. dirty_background_bytesі dirty_background_ratioподібні пороги, але промивання відбувається у фоновому режимі і не блокує інших операцій читання / запису, поки воно не завершиться. dirty_centisecsце скільки сантисекунд може пройти, перш ніж ініціювати флеш.

Нещодавно в Linux були зменшені значення за замовчуванням для цих змін, оскільки об'єм пам'яті для сучасних машин різко збільшився. Рівномірне співвідношення 5 і 10% для dirty_background_ratioта dirty_ratioна 256 ГБ машині може затопити систему вводу / виводу.

Налаштування dirty_background_bytesабо dirty_background_ratioпочати промивати брудні буфери на задньому плані є складним. На щастя, ви можете налаштувати ці налаштування, не зупиняючи ні PostgreSQL, ні хоста, повторюючи нові значення у відповідних файлах:

$ sudo echo [int value of bytes] > /proc/sys/vm/dirty_background_bytes

наприклад, встановити кількість забруднених байтів для запуску потоку фону. Якщо ви використовуєте батареї спинок, конденсатор спинок або флеш - пам'ять RAID - карти (ви дійсно хочете зберегти ваші дані в разі аварії, не так ли?) Почати з налаштуванням dirty_background_bytesдо 1/2 записи кеш розміру буфера і dirty_bytesдо 3/4 цього розміру. Контролюйте свій профіль вводу / виводу за допомогою йостатів, і якщо ви все ще спостерігаєте проблеми із затримкою, це означає, що завантаження вашої бази даних все ще переповнює кеш файлового буфера. Зменшіть значення до тих пір, поки затримка не покращиться або не подумайте про модернізацію вашої підсистеми вводу / виводу. Карти FusionIO і SSD - це дві можливості для надзвичайної пропускної здатності вводу / виводу.

Удачі!


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