Що таке sweep в interbase і firebird

Що ж таке sweep насправді, і чому коли він запускається в автоматичному режимі, він починає гальмувати роботу? Для тих, хто тільки знайомиться з сервером це виглядає як періодичні "гальма", які несподівано з'являються, тривають деякий час (до кількох годин), і так само несподівано зникають, причому незалежно від поточного навантаження (кількості коннектов і запитів, які в них виконуються ).

Власне, ця різниця між номерами транзакцій може виникнути при абсолютно різних умовах, тому як правило автоматичний sweep і стартує несподівано. Для позбавлення від таких несподіванок рекомендується встановлювати авто-sweep в 0 (gfix ​​db.gdb -housekeeping 0), і періодично запускати sweep вручну (gfix ​​db.gdb -sweep), в момент найменшої кількості активних коннектов, або взагалі в "монопольному" режимі .

Прибирання сміття буває двох типів:
  1. В архітектурі Classic (до InterBase 6.0, в Yaffil і Firebird) і SuperClassic (Firebird 2.5, 3.0) - сміттєві версії прибираються самим потоком (thread), який при читанні натрапив на версії.
  2. SuperServer (в InterBase 6.0 і вище, Firebird 2.5, 3.0) - при виявленні сміттєвих версій на сторінці (при читанні і оновленні) про це сигналізується потоку (thread) збирача сміття. Складальник сміття періодично збирає сміття на помічених сторінках.
Перша стратегія призводить до уповільнення select (читання записів) при складанні сміття. Друга стратегія призводить до уповільнення збірки сміття як такої - зокрема, при модифікації сторінки збирач сміття не знає, був він на цій сторінці вже чи ні. Крім того, потік (thread) збирача сміття при високому навантаженні сервера рідко отримує кванти часу для роботи, в результаті чого прибирання сміття виконується багато довше, ніж при першій стратегії (в InterBase 7.x в конфігурації введено параметр SWEEP_YIELD_TIME для затримки збірки сміття при його виявленні на n мілісекунд. А також SWEEP_QUANTUM, що визначає кількість "тиків" процесора, займаних складальником сміття).
Також, перешкоджати фонової збірці сміття може постійне і часте оновлення одних і тих же змінюваних сторінок даних - як тільки збирач сміття до них добирається, сторінки знову змінюються, і збирач сміття повинен почекати.
Ну і звичайно, при другій стратегії прибирання сміття може відбуватися невизначений час навіть після відключення клієнтських з'єднань, що робить небезпечною перезавантаження сервера в цей момент.

Примітка. Під "перезавантаженням сервера" мається на увазі штатна перезавантаження операційної системи з примусовим завершенням роботи служб. Точно так же сюди можна віднести натискання кнопки reset, відключення живлення і т. П. Що саме по собі може призвести до пошкодження бази даних, якщо в цей момент з нею інтенсивно працюють. Звичайна зупинка сервісу або програми Firebird або InterBase працює інакше, при цьому складання сміття будь-якого виду (фонова, кооперативна або sweep) припиняється коректно.

В Firebird 2.0 і вище можна управляти стратегією збірки сміття. Для цього в конфігурації (firebird.conf) є параметр GCPolicy, який має 3 варіанти:
  1. background - збирач сміття працює як фоновий, збираючи сміття окремим thread.
  2. cooperative - збирач сміття працює в кооперативному режимі, збираючи сміття негайно при читанні "сміттєвих" версій
  3. combined - збирач сміття працює в кооперативному режимі, але якщо сміття зібрати не вдається, то про "засмічених" сторінках сигнализируется фоновому збирачеві сміття.
Як сервер визначає, зчитується сміттєва версія записи, або вона ще комусь потрібна: версії потрібні в основному транзакціях snapshot. Як тільки стартує така транзакція, вона запам'ятовує наймолодший номер активної на даний момент транзакції. Відповідно, всі версії створені від такої "молодшої" транзакції до номера даного snapshot можуть породжувати версії, в яких зацікавлений даний snapshot. І ці версії "сміттям" не є. Тому нижче Oldest snapshot (тієї самої мінімальної активної на момент старту нині активного snapshot) версії записів можуть бути прибрані як сміття, а вище - немає.

Звідси вже зрозуміло, чому sweep призводить до суттєвих "гальмах" системи, будучи запущений по базі даних скільки-небудь значного розміру. Наприклад, по базі даних 2 гігабайти на середньої техніці вручну запущений sweep (gfix ​​-sweep db.gdb) працює протягом 2.5 хвилин, в монопольному режимі (це по базі, де немає версій записів взагалі. А прибирання сміття, зрозуміло, призводить до модифікацій сторінок, які повинні бути записані на диск). Причому, оскільки Новомосковскются всі сторінки даних і індексів, витісняється кеш БД, саме тому при багато користувачів роботі sweep сильно уповільнює виконання всіх запитів.

Таким чином, якщо у нас в БД виникає транзакція, скасована по rollback (знову ж таки, для якої сервер не зміг скасувати зміни по savepoints. Для різних версій сервера це різне значення, наприклад не менше 60 тисяч змінених записів), то це означає, що кожна наступна транзакція буде перевіряти версії на стан транзакцій від Next до Oldest. І чим більше цей інтервал, тим більше сторінок Transaction Inventory Page (зберігають стану транзакцій) буде зчитуватися в кеш, і тим більше цих сторінок будуть запам'ятовувати в "локальної пам'яті" транзакції snapshot.

Відповідно, просто з ростом числа транзакцій продуктивність буде деградувати.

Саме для того, щоб періодично зменшувати відстань від Next до Oldest і був введений автоматичний sweep.

додатково: