Конфлікти блокувань - мабуть, найпоширеніша і, в той же час, сложнорешаемая проблема при роботі з базою даних. Якщо, наприклад, для прискорення неоптимального коду можна просто наростити апаратні «м'язи»
Конфлікти блокувань - мабуть, найпоширеніша і, в той же час, сложнорешаемая проблема при роботі з базою даних. Якщо, наприклад, для прискорення неоптимального коду можна просто наростити апаратні «м'язи» і на якийсь час забути про проблему, то з блокуваннями такий трюк не пройде: бездумні рішення тут майже не дають віддачі, для виправлення ситуації доводиться включати голову і шукати корінь проблеми. У цій статті ми якраз і розберемо найбільш популярні «корінці», з якими найчастіше доводиться стикатися, розплутуючи випадки зависання користувачів.
Відзначимо, що самі по собі блокування ні в якому разі не є непримиренним злом, з яким потрібно боротися всіма можливими способами. Навпаки, блокування ресурсів - надзвичайно важливий механізм багатокористувацької системи, завдяки якому забезпечується несуперечність і цілісність оброблюваних даних. Блокування, накладена користувачем, гарантує, що необхідні дані не будуть змінені інший транзакцією, а значить - користувач отримає очікуваний результат виконання операції. Але ось коли транзакції починають блокувати надлишкові ресурси, необов'язкові для виконання поточного завдання - починаються проблеми, «зависання» користувачів, ефективність роботи різко падає. Саме з такими проблемами ми і будемо боротися.
Перш ніж почати розбір проблем, обговоримо пару важливих моментів:
Перше. Тут не буде опису класичних артефактів читання, способів боротьби з ними; рівні ізоляції транзакцій будуть розглянуті побіжно. Та все це - досить загальна теорія, яка і так напевно відома читачеві. При необхідності освіжити знання можна в тому ж MSDN (Рівень ізольованості транзакцій), а в цій статті, орієнтованої більше на практику, розлогий теоретичний екскурс буде явно зайвим.
Давним-давно, в далекій-далекій ...
Видно, що більше 20 користувачів висять на блокування, чекаючи завершення транзакції користувача 449. Пошук в MSDN по «типу очікування» підказує, що всі ці користувачі збираються щось записати в таблицю; опис ресурсу ( «TAB») говорить про те, що заблокована не якась дрібна область, а ціла таблиця.
Невелике розслідування показує, що найчастіше блокування виникають на таблиці _1SJOURN - єдиному журналі документів в 1С 7.7. У цій таблиці зберігаються дата, номер і ідентифікатор кожного документа, виписаного в програмі. Проблема в тому, що в момент проведення будь-якого документа накладається ексклюзивна блокування на всю таблицю. Саме так: навіть якщо користувачі проводять різні види документів, в один момент часу може бути записаний тільки один документ. При великому вхідному потоці документів (наприклад, велике число заявок з дрібнооптового магазину) така поведінка стає серйозною проблемою.
. Іноді вони повертаються
Дерево блокувань показує підозріло знайому картину: очікування ексклюзивної блокування (LCK_M_IX), причому заблокована ціла таблиця (TAB). Ну хоч таблиця окремого документа, а не єдиного журналу - і то добре! Що, знову 1С «полінувалася»? Насправді провини розробника платформи тут немає. 1С 8.х в своїх запитах ніколи не накладає табличних блокувань (за винятком випадків роботи з тимчасовими таблицями - але ж такі таблиці «живуть» тільки в рамках одного сеансу, нам і так їх не з ким ділити, так що можна сміливо блокувати її всю - ніхто не образиться). У такій ситуації в гру вступають більш глибокі механізми - а саме, ескалація блокувань на рівні MS SQL.
Кожна блокування сама по собі - об'єкт, облуживание якого вимагає процесорного часу і оперативної пам'яті. Так, звичайно, одна блокування в масштабах сучасного сервера помітна не більше, ніж бджола в величезному ангарі. Але от коли таких бджіл набереться цілий рій ... Приблизно так міркує СУБД, оцінюючи кількість блокувань, що накладаються на таблицю. Спочатку, якщо програма не дає явних вказівок (а 1С таких вказівок не дає!), На таблицю накладаються «точкові» блокування рівня запису або сторінки даних. Але коли СУБД бачить велике число блокувань на одну і ту ж таблицю, з однієї і тієї ж транзакції, або ж коли в системі відчувається дефіцит вільної оперативної пам'яті, приймається рішення: замість рою дрібних блокувань накласти одну, але велику. В результаті навантаження на апаратні ресурси знижується, правда захопленими виявляються навіть ті рядки таблиці, які в транзакції зовсім не були потрібні. Користувачі починають частіше стикатися з-за конкуренції за одні й ті ж таблиці, зате ресурси використовуються більш економно.
Перед тим, як боротися з ескалацією блокувань непогано буде зрозуміти, через що вони все-таки виникають. Можливо, в програмі використовуються занадто довгі транзакції, що змінюють дані великими пачками. Або, дійсно, системі просто недостатньо вільної оперативної пам'яті. У таких випадках необхідно лікувати причину, а не наслідок - кожна із ситуацій чревата і іншими проблемами, ескалація блокувань - не найстрашніша з них.
Повертаючись до 1С, слід враховувати, що будь-які маніпуляції з таблицями безпосередньо в базі даних (зміна опцій, додавання індексів і т.п.) не запам'ятовуються конфігуратором і можуть бути перезаписані при черговій реструктуризації. Так що варто окремо підготувати скрипт, що відключає ескалацію по потрібним таблицями, і виконувати його після оновлення конфігурації. Благо, сама операція відключення ескалації займає частки секунди.
З іншого боку - в адмініструванні баз даних не буває «правильних» рішень, які застосовні скрізь і завжди. Якщо користувачі рідко стикаються з табличними блокуваннями, переважають короткі транзакції або база взагалі не доросла до обсягів, коли ескалації стануть проблемою, відключення ескалації не допоможе прискорити роботу користувачів, але, навпаки, призведе до надмірного споживання ресурсів. Як і завжди в адмініструванні БД - будь-який засіб слід використовувати тільки при наявності явних показань і при ясному розумінні наслідків.
Всі наведені ілюстрації отримані із застосуванням системи моніторингу PerfExpert