Блокировки в системе 1С. Эксперименты.

В этих несложных опытах мы наглядно рассмотрим, как работают блокировки в системе 1С.

ПОДГОТОВКА

Для проведения экспериментов с блокировками в 1С необходимо в пустую серверную базу с использованием СУБД MS SQL загрузить тестовую базу.
Так как в управляемом интерфейсе модули документов выполняются на стороне сервера, поэтому перед выполнением экспериментов необходимо разрешить отладку на сервере. Для этого необходимо зайти в ветку реестра:
HKLM->System->CurrentControlSet->Services->1C:Enterprise 8.3 Server Agent, находим строковый параметр ImagePath, открываем для редактирования и добавляем в самом конце него ключ –debug.
Например, было:
«C:\Program Files\1cv8\8.3.5.1098\bin\ragent.exe» -srvc -agent -regport 1541 -port 1540 -range 1560:1591 -d «C:\Program Files\1cv8\srvinfo»
стало:
«C:\Program Files\1cv8\8.3.5.1098\bin\ragent.exe» -srvc -agent -regport 1541 -port 1540 -range 1560:1591 -d «C:\Program Files\1cv8\srvinfo» –debug.

Внимание! Перед каждым экспериментом рекомендуется перезагружать тестовую базу, чтоб изменения, сделанные в предыдущем опыте, не повлияли на результаты следущих!

Опыт 1. READ_COMMITTED и отрицательные остатки.

В тестовой базе введен документ «Поступление» на 1000 единиц и два документа «Реализация» на 600 единиц каждая. Если проводить реализацию последовательно, то при проведении второго документа появиться ошибка отсутствия остатков и документ не проведется, но если:
1. Запустить конфигуратор.
2. Открыть модуль документа «Реализация».
3. Поставить точку останова после выполнения запроса по остаткам до записи в регистр.

Блокировки в системе 1С

4. Запустить отладку.
5. Открыть список документов «Реализация».
6. Убедиться что первый документ (Реализация №000000001 от 20.08.2014 9:47:39) не проведен (если проведен, то сделать его непроведенным из контекстного меню).
7. Провести первый документ из контекстного меню.
8. Убедиться что сработала точка останова.

Блокировки в системе 1С

9. Запустить второй сеанс 1С.
10. Второй сеанс: открыть список документов «Реализация».
11. Второй сеанс: провести (перепровести) второй документ «Расходная накладная».
12. Второй сеанс: убедиться что второй документ успешно провелся и списал 600 единиц.

Блокировки в системе 1С

13. Переключиться в конфигуратор и продолжить отладку.
14. Первая сессия: убедиться что первый документ успешно провелся и списал 600 единиц.
15. Документ провелся и списалось еще 600.

Блокировки в системе 1С

16. В результате получили отрицательный остаток на складе -200.
18. Расскоментируем код установки управляемой блокировки и повторяем эксперимент. При включении управляемой блокировки видим, что при незавершенной транзакции система не позволила провести документ:

Блокировки в системе 1С

Вывод: для исключения таких проблем с READ_COMMITTED необходимо использовать управляемые блокировки 1С — устанавливать исключительную управляемую блокировку перед выполнением запроса.

Опыт 2. READ_COMMITTED_SNAPSHOT в 8.3.

1. Запустить конфигуратор.
2. Загрузить заново test.dt или закомментировать код установки управляемой блокировки.
3. Установить в свойствах конфигурации режим совместимости «Не использовать».

Блокировки в системе 1С

4. Открыть модуль документа «Расходная накладная» и поставить точку останова после записи в регистр.

Блокировки в системе 1С

5. Запустить отладку.
6. Открыть список документов «Реализация».
7. Провести первый документ из контекстного меню.
8. Убедиться что сработала точка останова.
9. Запустить второй сеанс 1С.
10. Второй сеанс: открыть список документов «Расходная накладная».
11. Второй сеанс: провести (перепровести) второй документ «Расходная накладная».
12. Второй сеанс: убедиться что второй документ успешно провелся и списал 600 единиц..

Блокировки в системе 1С

Вывод: при обычном READ_COMMITTED (режим совместимости 8.2) второй документ не провелся бы из-за таймаута ожидания установки S блокировки на время выполнения запроса, так как эти данные заблокированы первым сеансом (установлена X блокировка при записи в регистр до конца транзакции). При READ_COMMITTED_SNAPSHOT «S» блокировка на время чтения (выполнения запроса) не устанавливается, а второй сеанс (при выполнении запроса) получила копию данных, которая была в базе до начала выполнения транзакции из первой сессии.
13. Переключиться в конфигуратор и продолжить отладку
14. Первая сессия: Убедиться что первый документ успешно провелся и списал 600 единиц. В результате получили отрицательный остаток на складе -200.

Блокировки в системе 1С

15. Раскоментируем код установки управляемой блокировки и повторяем эксперимент.

Результат: уровень изоляции «READ_COMMITTED_SNAPSHOT» исключает «S» блокировку при чтении в транзакции, что увеличивает параллельность работы. В случае контроля остатков нас это не спасает, потому что все равно необходимо устанавливать исключительную управляемую блокировку перед выполнением запроса.

Опыт 3. Разделитель итогов.

Почему в опыте 2 прошла параллельная запись в регистр?
С помощью SQL Server Management Studio убедиться что в структуре физической таблицы итогов регистра «Остатки» присутствует поле «Splitter». Таблица итогов регистра накопления имеет суффикс «T» для регистров остатков и «Tn» — для регистров оборотов. Посмотреть какими значениями заполнено поле «Splitter».
В конфигураторе для регистра «Остатки» отключим возможность использования итогов (по умолчанию для новых регистров эта возможность всегда включена)
После реструктуризации просмотреть структуру физические таблицы итогов регистра «Остатки» в SSMS и убедиться в отсутствии поля «Splitter».

Провести опыт 2 и убедится что возникнет ошибка ожидания на блокировках.

Блокировки в системе 1С

Выводы: использование разделителя итогов дает возможность параллельной записи в регистр (именно в таблицы итогов), но уменьшают скорость получения остатков, так как таблицы «расслоены» по значению разделителя.

Опыт 4. Разделитель итогов и «БлокироватьДляИзменения».

Включим использование разделителя итогов для регистра «Остатки» и раскомментируем строку «Движения.Остатки.БлокироватьДляИзменения = Истина» (перед записью наборов). Также убедимся что раскоментирован код установки управляемой блокировки.
Снова проведем опыт 2 и убедимся что возникнет ошибка ожидания блокировки.

Блокировки в 1С

Вывод: при установленном свойстве «БлокироватьДляИзменения» управляемая блокировка при записи наборов регистра устанавливается без учета разделителя (по всем разделителям). Такое действие запрещает параллельную запись в регистр из других сеансов, что гарантирует неизменность итогов регистра до конца транзакции.

Опыт 5. Управляемые блокировки и фантомная вставка.

1. Открыть в конфигураторе модуль объекта документа «Реализация» и найти процедуру «ПередЗаписью()».
2. Убедиться что код установки управляемой блокировку в начале процедуры закомментирован (управляемая блокировка не устанавливается).
3. Установить точку останова на строку 112 процедуры:

Блокировки в 1С. Эксперименты.

4. Запустить отладку.
5. Открываем документ «Реализация №000000001 от 20.08.2014 9:47:39». Очищаем в табличной части цену, что бы она определилась автоматически при записи документа по данным регистра сведений «Цены номенклатуры».
6. Проводим документ
7. Проверить что сработала точка останова.
8. Запустить второй сеанс 1С.
9. Второй сеанс: открыть список документов «Поступление»
10. Второй сеанс: из контекстного меню проводим документ «Поступление №000000003 от 20.08.2014 8:00:00».
11. Конфигуратор: продолжить работу, остановленную на точке останова.
12. Первый сеанс: в окне сообщений видим разные результаты выполнения одного запроса «Цена 10, Цена 11».

Блокировки в 1С. Эксперименты.

13. Второй сеанс: из контекстного меню отменяем проведение документа «Поступление №000000003 от 20.08.2014 8:00:00».
14. Закрываем оба сеанса. Переходим в конфигуратор.
15. Уберем комментарии с кода установки управляемой блокировки в начале процедуры «ПередЗаписью()».
16. Запустим отладку и повторим опыт с шага 5.
17. Убедимся что при проведении документа «Поступление №000000003 от 20.08.2014 8:00:00» в сессии 2 возникла ошибка блокировки:

Блокировки в системе 1С

Вывод: установка управляемой блокировки позволяет решить проблему чтения фантомной вставки. Если в транзакции несколько раз происходит чтение одних и тех же данных из базы, то необходимо устанавливать управляемую блокировку. Используя временные таблицы можно исключить повторное чтение данных из базы.

Опыт 8. Взаимоблокировки из-за повышения уровня блокировки.

1. Установить точку останова в модуле документа «Реализация», в строке 86 (Движения.Остатки.Записать())

Блокировки в 1С

2. Установить (раскомментировать) разделяемую управляемую блокировку перед запросом

Блокировки в системе 1С

3. Запустить отладку
4. Убедиться что документы «Реализация №000000001 от 20.08.2014 9:47:39» и «Реализация №000000002 от 20.08.2014 11:33:00» не проведены. Если проведены, то отменить проведение.
5. В документе Реализация №000000002 изменить количество товара с 600 на 400
6. Провести документ «Реализация №000000001 от 20.08.2014 9:47:39» и убедиться, что сработала точка останова.
7. Запустить второй сеанс 1С.
8. Второй сеанс: провести документ «Реализация №000000002 от 20.08.2014 11:33:00» и в течение 20 секунд:
— конфигуратор: продолжить работу, остановленную на точке останова;
— убедиться что в одной из сессий возникла ошибка взаимоблокировки.

Блокировки в 1С

9. Установить исключительную управляемую  блокировку.

Блокировки в системе 1С

10. Повторить опыт и убедиться что оба документа провелись без возникновения блокировок.
11. Повторить опыт, но не запускать сеанс с точки останова. Получаем конфликт ожидания на управляемых блокировках.

Блокировки в системе 1С

Опыт 9. Взаимоблокировки из-за захвата ресурсов в разном порядке.

1. Отключить разделитель итогов у регистров накопления «Остатки» и «Продажи».

Блокировки в 1С
2. Установить точку останова в модуле документа «Реализация», в строке Движения.Продажи.Записать().

Блокировки в 1С

3. Запустить отладку.
4. Убедиться что документы «Реализация №000000001 от 20.08.2014 9:47:39» и «Возврат №000000001 от 22.08.2014 12:00:00» не проведены. Если проведены, то отменить проведение.
5. Провести документ «Реализация №000000001 от 20.08.2014 9:47:39» и убедиться что сработала точка останова.
6. Запустить второй сеанс1С.
7. Второй сеанс: провести документ «Возврат №000000001 от 22.08.2014 12:00:00» и в течение 20 секунд:
— конфигуратор: продолжить работу, остановленную на точке останова;
— убедиться что в одной из сессий возникла ошибка взаимоблокировки.

Блокировки в 1С

9. Поменять местами строки «Остатки.Записать()» и «Продажи.Записать()» в документе «Возврат»
10. Повторить опыт и убедиться что взаимоблокировки не возникает.

Опыт 10. Взаимоблокировка СУБД при контроле остатков после записи.

1. Включить режим совместимости 8.2.
2. Для регистра накопления «Остатки» включить разделитель итогов.
3. Установить точку останова в документе «Списание» на строку «Запрос.Выполнить».
5. Запустить первый сеанс 1С из отладчика.
6. Провести документ «Списание 1».
7. Проверить что сработала точка останова.
8. Запустить второй сеанс 1С.
9. Второй сеанс: провести док «Списание 2» в течение 20 секунд пока второй сеанс заблокирован).
10. В конфигураторе продолжить работу первого сеанса с точки останова
11. Получить взаимоблокировку на стороне СУБД.
12. Зафиксировать контекст ошибки взаимоблокировки.

Блокировки в 1С

13. Раскомментировать строку «БлокироватьДляИзменения = Истина».
14. Повторить опыт и убедиться, что взаимоблокировки не происходит.

Блокировки в 1С

15. Повторить опыт, но не продолжать работу первого сеанса с точки останова.
16. Убедиться, что происходит ошибка ожидания управляемых блокировок.
17. Зафиксировать контекст ошибки ожидания управляемой блокировки.

Блокировки в 1С

После проведения опыта, ответьте на следущие вопросы:
1. Почему возникала взаимоблокировка СУБД?
2. Почему установка «БлокироватьДляИзменения» исключило взаимоблокировку?
3. Почему появилась ошибка упр. блокировки?
4. Зачем установили режим совместимости 8.2?
5. К какому типу можно отнести такую взаимоблокировку?

Posted in Блог Оптимизации 1С.

One Comment

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *