Мобильная платформа. Конфликт блокировок.

1. VitaliyCeban 461 22.08.17 14:32 Сейчас в теме
Добрый день!

Столкнулся с проблемой конфликта блокировок на мобильной платформе.
Версии мобильной платформы: 8.3.10.51, 8.3.10.62. Android 6.0

В мобильной конфигурации используется план обмена. Обмен с центральной базой через HTTP-сервис.

Каждые 2-3 секунды получаются текущие координаты GPS и записываются в регистр сведений.
Получение координат реализовано через подписку СредстваГеопозиционирования.ПодключитьОбработчикИзмененияМестоположения.

Процедура ЗаписатьМестоположениеВИсторию(Местоположение) Экспорт
	
	ТекущийПользователь = ПараметрыСеанса.ТекущийПользователь;
	КоординатыМестоположения = Местоположение.Координаты;
	
	НаборЗаписей = РегистрыСведений.ИсторияМестоположения.СоздатьНаборЗаписей();
	НаборЗаписей.Отбор.Период.Установить(Местоположение.Дата);
	НаборЗаписей.Отбор.Пользователь.Установить(ТекущийПользователь);
	
	Запись = НаборЗаписей.Добавить();
	Запись.Период					= Местоположение.Дата;
	Запись.Пользователь				= ТекущийПользователь;
	Запись.Высота					= КоординатыМестоположения.Высота;
	Запись.Долгота					= КоординатыМестоположения.Долгота;
	Запись.Широта					= КоординатыМестоположения.Широта;
	Запись.Направление				= Местоположение.Направление;
	Запись.Скорость					= Местоположение.Скорость;
	Запись.ВертикальнаяТочность		= Местоположение.ВертикальнаяТочность;
	Запись.ГоризонтальнаяТочность	= Местоположение.ГоризонтальнаяТочность;
	
	НаборЗаписей.Записать();
	
КонецПроцедуры
Показать

Каждые 10 секунд выполяется фоновое задание, в котором происходит обмен.
Так как в обмене "мобильный -> сервер" участвуют изображения по 5mb, то чтобы не блокировать работу на всё время отправки сообщения, была реализована выборка изменений в очередь сообщений, и затем уже отдельная отправка, не блокирующая таблицы изменений.

Процедура СформироватьПакетыОбменаИДобавитьВОчередь(Узел) Экспорт
	
	Попытка
		НачатьТранзакцию();

		МассивОбъектов = Новый Массив;
		Выборка = ПланыОбмена.ВыбратьИзменения(Узел, 0);
		Пока Выборка.Следующий() Цикл
			Объект = Выборка.Получить();
			МассивОбъектов.Добавить(Объект); 
		КонецЦикла; 
		
		ПорцияОбъектов = Новый Массив;
		Для Сч = 1 По МассивОбъектов.Количество() Цикл
			Объект = МассивОбъектов[Сч - 1];	
			
			ПорцияОбъектов.Добавить(Объект);
			ПланыОбмена.УдалитьРегистрациюИзменений(Узел, ?(ТипЗнч(Объект) = Тип("Структура"), Объект.Ссылка, Объект));
			
			Если Сч % 50 = 0 И ПорцияОбъектов.Количество() > 0 Тогда
				ТекстСообщения = РаботаСJSON.СериализоватьВJSON(ПорцияОбъектов);
				ДобавитьСообщениеОбменаВОчередь(Узел, ТекстСообщения);
				ПорцияОбъектов = Новый Массив;
			КонецЕсли; 
		КонецЦикла; 
		
		Если ПорцияОбъектов.Количество() > 0 Тогда
			ТекстСообщения = РаботаСJSON.СериализоватьВJSON(ПорцияОбъектов);
			ДобавитьСообщениеОбменаВОчередь(Узел, ТекстСообщения);
			ПорцияОбъектов = Новый Массив;
		КонецЕсли;
		
		ЗафиксироватьТранзакцию();
	Исключение
	    ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки; 
	
КонецПроцедуры
Показать

С очень частой периодчностью (раз в несколько минут) появляется сообщение о конфликте блокировок.

В основном сеансе при

НаборЗаписей.Записать();

Конфликт блокировок при выполнении транзакции:
Не удалось заблокировать таблицу '_InfoRgChngR275'

а в фоновом задании при

Объект = Выборка.Получить();

Ошибка при вызове метода контекста (Получить):
Конфликт блокировок при выполнении транзакции:  <и тут пусто, нет подробностей>

Сервер и блокировки на стороне сервера из за множества одновременных сеансов по обмену - тут вообще не причем.

Авторегистрация по регистру отключена. Регистрация происходит путем

Объект.ОбменДанными.Получатели.Добавить(УзелЦБ); 

в подписке на событие ПередЗаписью

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


Помогите понять куда копать, как получить больше информации о причинах, как устранить... Спасибо.
+
Ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. Dream_kz 129 22.08.17 14:56 Сейчас в теме
(1)
Согласно логике, в этом случае один сеанс должен будет ждать другой какое-то непродолжительное время, а затем продолжить работу.
А на деле происходит дед-лок, вроде-бы, на ровном месте.

Ну так блокируйте данные, блокировки то управляемые, ожидание и будет.
+
3. VitaliyCeban 461 22.08.17 15:13 Сейчас в теме
(2)
Ну так блокируйте данные, блокировки то управляемые, ожидание и будет.


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

		МассивОбъектов = Новый Массив;
		Выборка = ПланыОбмена.ВыбратьИзменения(Узел, 0);
...
Показать


Так должно работать, но это же ненормальный костыль. Да и "ПланыОбмена.ВыбратьИзменения" и так должен блокировать всё что нужно.
+
4. Dream_kz 129 22.08.17 16:08 Сейчас в теме
(3)
так должен блокировать всё что нужно

Ну не факт, может поведение в управляемом режиме на мобильной платформе отличается
+
Внимание! Тема сдана в архив

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот