Як визначити рівень ізоляції запиту
Це питання виникло у нас на проекті з впровадження ЗУП2.5 з чисельністю 20000 та максимальною кількістю одночасних користувальницьких сесій 200.
На етапі дослідної експлуатації під час розрахунку зарплати користувачі почали інтенсивно працювати з документами «Нарахування зарплати працівникам організацій». Кількість рядків документів сягала 2500 рядків. У користувачів почали з'являтись повідомлення «Конфлікт блокувань при виконанні транзакції», і розрахунок доводилося запускати заново.

Почали розбиратися. Виявилося, що ми зіткнулися з ефектом «Надлишкового блокування». Зазвичай цей ефект виникає при паралельному проведенні документів. Якщо по-простому, один із документів блокує великий обсяг даних на весь час проведення документа. Це блокування затримує проведення інших документів, які намагаються прочитати заблоковані дані. Це заважає паралельній роботі користувачів та уповільнює робочий процес. Взагалі, блокування даних при проведенні документів річ корисна, вона зберігає цілісність даних і гарантує правильність виконання розрахункових алгоритмів. Але буває так, що обсяг заблокованих даних надмірний, або час блокування занадто великий. В результаті ми маємо розраховану на багато користувачів систему, яка по суті є однокористувальною: замість паралельного проведення документів - послідовне.
Розглянемодва приклади з необхідним блокуванням і з надлишковим.
Звісно, цей приклад притягнутий за вуха для простоти пояснення. Насправді логіка ЗУП 2.5 така, що для подвоєння ПДФО користувачам не потрібно докладати особливих зусиль. ПДФО розраховується до проведення документа, а при проведенні вмісту табличної частини простозаноситься до регістру без жодної перевірки. Користувачам між розрахунком та проведенням надається можливість подивитися майбутній результат та за необхідності поправити руками. Звичайно, це великий плюс на користь гнучкості ЗУПу, але пред'являє високі вимоги до професійного рівня розрахунків. Тому питання запобігання задвоєнню ПДФО вирішується організаційним шляхом або за допомогою додаткових перевірочних звітів. Звичайно, у ЗУП2.5 є регістри, які розраховуються та записуються одночасно при проведенні документа, наприклад «ПДФО до заліку», але цей приклад довелося б довше пояснювати ;).
А тепер уявимо іншу ситуацію. Під час проведення документа виконується запит, який має відібрати документи, у яких присутні співробітники цього документа. Але запит написано так, що сервер SQL змушений знаходити необхідні документи шляхом перебору. Для експерта з технологічних питань це, що замість INDEX SEEK виконується TABLE SCAN, тобто. замість пошуку таблиці індексів відбувається послідовний перебір записів у самій таблиці. Причому в процесі перебору блокуються всі записи, до яких доторкнувся запит, навіть ті, у яких відсутні співробітники. І це блокування діятиме до кінця завершення проведення документа, що перешкоджатиме паралельному проведенню документів з іншими співробітниками. Ценадлишкове блокування.
Лікування надлишкових блокувань може йти двома шляхами. Перший - це оптимізація запитів, що виконуються всередині транзакцій та додавання необхідних табличних індексів у конфігураторі. Другий - це переклад виконання SQL-запитів на найнижчий рівень ізоляції, коли під час виконання запитів записи у таблицях блокуються лише у момент виконання самого запиту, чи неблокуються зовсім. А необхідні блокування встановлюються засобами об'єкта «БлокуванняДаних» та виконуються на стороні сервера 1С.
Тепер трохи теорії про рівні ізоляції на SQL сервері:
- В автоматичному режимі у транзакціях використовується рівень ізоляції SERIALIZABLE. Цей рівень накладає на таблиці з даними блокування типу S (забороняє запис та перевіряє чи немає в цей момент паралельних записів) до кінця транзакції на всі дані, яких торкнулися запити, та блокування типу X (забороняє читання та запис) на всі дані, за якими відбувся запис. На таблиці індексів також до кінця транзакції накладаються блокування типу RangeS у запитах та RangeX при записі.
- У режимі керування в транзакціях використовується рівень ізоляції READ COMMITTED. Цей рівень записаних даних також встановлює блокування типу X до кінця транзакції. Але при виконанні запитів на дані накладає блокування типу S, а при завершенні запиту блокування знімається, не чекаючи завершення транзакції. На таблиці індексів жодних блокувань не накладається.
- Якщо базу даних переведено в режим READ COMMITTED SNAPSHOT, то в керованому режимі під час читання даних не накладається блокування типу S, є лише блокування типу X під час запису.