Разбор причины ошибки "Нарушение целостности чтения объекта базы данных из-за параллельного изменения объекта другим сеансом"

25.06.21

База данных - Технологический журнал

При нагруженной работе начали возникать ошибки чтения из-за параллельного изменения. Здесь приводится расследование причин проблемы.

О стенде и инструментах

Тестовый стенд: режим управления блокировками управляемый, версия платформы 8.3.12.

Для расследования проблемы использовался технологический журнал (далее по тексту ТЖ).
Более подробно о нем написано написано в публикациях Рецепты приготовления технологического журнала и Описание почти всех событий технологического журнала.

 

Описание ошибки в ЖР

Расследуемая ошибка в журнале регистрации выглядит так:

 

Случай 1 (объектное чтение ПолучитьОбъект())

Воспроизведение

Для воспроизведения проблемы создадим множество потоков на запись следующим кодом

Процедура ЗапуститьФоновыеЗадания(Кнопка)
	
	// Обработка сделана для расследования ошибки:
	// Нарушение целостности чтения объекта базы данных из-за параллельного изменения объекта другим сеансом
	
	МассивПараметров = Новый Массив;
	МассивПараметров.Добавить(Документ);
	МассивПараметров.Добавить(1);
	
	Для Инд = 1 по 100 Цикл
		
		ФоновыеЗадания.Выполнить("Привилегированный.Записать", МассивПараметров, "КлючЗаписать " + Инд);
		ФоновыеЗадания.Выполнить("Привилегированный.Записать", МассивПараметров, "КлючЗаписатьДублирующий " + Инд);
		
	КонецЦикла;
	
КонецПроцедуры

Процедура Записать(Документ, Значение) Экспорт
	
	ДокументОбъект = Документ.ПолучитьОбъект();
	ДокументОбъект.Реквизит = Значение;
	ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
	
КонецПроцедуры

Расследование

Посмотрим на события в ТЖ:

 

Видим последовательность действий по документу ID=282:ae5600505699b66311e9899bd8fdecc8

  1. Наложения неявной блокировки платформой при записи (07:16.164118 TLOCK)
  2. Обновление в СУБД данных документа (07:19.321016 SDBL ... 'UPDATE ...')
  3. Фиксация транзакции вместе с этими изменениями (07:20 SDBL)
  4. Объектное чтение во время фиксации данных объекта (07:20.430016 SDBL, обращаем внимание на чтение версии по документу ID=282:ae5600505699b66311e9899bd8fdecc8)
  5. Ошибку чтения из-за параллельного изменения (07:20.430017 EXCP)

Исправление ошибки

Избежать ошибки можно организовав очередь к документу наложив явную управляемую блокировку перед записью документа

Процедура ЗаписатьСБлокировкой(Документ, Значение) Экспорт
	
	НачатьТранзакцию();
	
	Попытка
		
		Блокировка = Новый БлокировкаДанных;
		ЭлементБлокировки = Блокировка.Добавить();
		ЭлементБлокировки.Область = "Документ.РеализацияТоваровУслуг";
		ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
		ЭлементБлокировки.УстановитьЗначение("Ссылка", Документ);
		Блокировка.Заблокировать();
		
		ДокументОбъект = Документ.ПолучитьОбъект();
		ДокументОбъект.Реквизит = Значение;
		ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
		
		ЗафиксироватьТранзакцию();
		
	Исключение
		
		ПодробнаяОшибка = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		ЗаписьЖурналаРегистрации("Ошибка записи", УровеньЖурналаРегистрации.Ошибка,, ПодробнаяОшибка);
		
		ОтменитьТранзакцию();
		
	КонецПопытки;
	
КонецПроцедуры

В ТЖ будет видно 2 исхода события

1. Успешное наложение блокировки и ожидание 2 потоком пока 1 отработает

2. Неудачная попытка блокировки и откат транзакции

 

Случай 2 (объектное чтение Ссылка.Товары.НайтиСтроки())

Воспроизведение

Рассмотрим аналогичный случай при чтении табличной части документа


Процедура ЗапуститьФоновыеЗадания(Кнопка)
	
	// Обработка сделана для расследования ошибки:
	// Нарушение целостности чтения объекта базы данных из-за параллельного изменения объекта другим сеансом
	
	Склад = Справочники.Склады.НайтиПоКоду("КодСклада");
	
	МассивПараметровЗаписи = Новый Массив;
	МассивПараметровЗаписи.Добавить(Документ);
	МассивПараметровЗаписи.Добавить(1);
	
	МассивПараметровЧтения = Новый Массив;
	МассивПараметровЧтения.Добавить(Документ);
	МассивПараметровЧтения.Добавить(Склад);
	
	Для Инд = 1 по 100 Цикл
		
		ФоновыеЗадания.Выполнить("Привилегированный.Записать", МассивПараметровЗаписи, "КлючЗаписать " + Инд);
		ФоновыеЗадания.Выполнить("Привилегированный.Прочитать", МассивПараметровЧтения, "КлючПрочитать " + Инд);
		
	КонецЦикла;
	
КонецПроцедуры

Процедура Записать(Ссылка, Значение) Экспорт
	
	ДокументОбъект = Ссылка.ПолучитьОбъект();
	ДокументОбъект.Значение= Значение;
	ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
	
КонецПроцедуры

Процедура Прочитать(Ссылка, Склад) Экспорт
	
	Ссылка.Товары.НайтиСтроки(Новый Структура("Склад", Склад));
	
КонецПроцедуры

Расследование

Посмотрим на события в ТЖ:

Видим последовательность по документу ID=282:ae5600505699b66311e9899bd8fdecc8

  1. Наложения неявной блокировки платформой при записи (04:57.680428 TLOCK)
  2. Обновление в СУБД данных документа (04:57/996003 SDBL ... 'UPDATE ...')
  3. Фиксация транзакции вместе с этими изменениями (05:02 SDBL)
  4. Объектное чтение во время фиксации данных объекта (05:02.528150 SDBL, обращаем внимание на чтение версии по документу ID=282:ae5600505699b66311e9899bd8fdecc8)
  5. Ошибку чтения из-за параллельного изменения (05:02.528151)

 

Исправление ошибки

Избежать ошибки можно наложив явную управляемую блокировку перед записью документа или заменив объектное чтение чтением через запросы.

В ТЖ видно чтение через запросы и отсутствие ошибок

Заключение:

Ошибка связана с объектным чтением в момент принятия изменений платформой.
В зависимости от причины ошибки возможны два пути решения:

  1. организовать очередь используя управляемую блокировку (возможно повторение ошибки при доработках)
  2. переделать объектное чтение на чтение через запросы (повторение ошибки исключено)

 

См. также

HighLoad оптимизация Технологический журнал Системный администратор Программист Бесплатно (free)

Обсудим поиск и разбор причин длительных серверных вызовов CALL, SCALL.

24.06.2024    5156    ivanov660    12    

56

Технологический журнал Мониторинг Системный администратор Программист Абонемент ($m)

Как легко и быстро с помощью специализированных решений собирать, парсить и передавать логи и метрики.

1 стартмани

15.11.2023    1572    8    AlexSTAL    0    

8

Мониторинг Журнал регистрации Технологический журнал Системный администратор Программист Абонемент ($m)

Как легко и быстро с помощью специализированных решений собирать, парсить и передавать логи и метрики.

1 стартмани

13.11.2023    4737    9    AlexSTAL    0    

47

Администрирование СУБД Технологический журнал Системный администратор Бесплатно (free)

Для расследования проблем производительности недостаточно просто проанализировать технологический журнал. Нужен парсинг контекста событий, его сопоставление с информацией из Extended Events и логов, агрегация огромного количества информации.

21.09.2023    7264    Andreynikus    14    

83

Технологический журнал Системный администратор Программист Платформа 1С v8.3 Абонемент ($m)

Целью данного решения является организация хранения и анализа данных из технологического журнала 1С с использованием стека Elasticsearch + Logstash + Kibana.

5 стартмани

18.09.2023    5093    huxuxuya    6    

27
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. alexeyo51 02.11.22 12:01 Сейчас в теме
Встретился случай, когда такая ошибка возникает без записи объекта в другом сеансе, а при последовательной записи в рамках одного сеанса.
Более того ошибка - при записи набора записей с уникальным отбором (движение для нового документа).
2. pashamak 338 02.11.22 12:22 Сейчас в теме
(1) Интересно посмотреть на пример. Может срабатывает отложенное проведение в ФЗ которое остается без внимания.
Оставьте свое сообщение