Меню


Курсы СтимулСправочникПолезные материалы1С:Предприятие 8.2РазработчикамРеализация обработки данных

1С:Предприятие 8.2 /
Разработчикам /
Реализация обработки данных

Оглавление

Использование транзакций при чтении данных

Использование чтения вне транзакции

См. также

 

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

Неправильно:

// 1. Прочитать  регистр сведений 
Запрос = Новый Запрос(
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| ЗаметкиПоПредмету.КоличествоЗаметок КАК КоличествоЗаметок
|ИЗ
|  РегистрСведений.ЗаметкиПоПредмету  КАК ЗаметкиПоПредмету
|ГДЕ
| ЗаметкиПоПредмету.Предмет = &Предмет");
Запрос.УстановитьПараметр("Предмет", ПредметЗаметок);
Выборка = Запрос.Выполнить().Выбрать();

КоличествоЗаметок = 0;
Если Выборка.Следующий() Тогда
КоличествоЗаметок = Выборка.КоличествоЗаметок;
КонецЕсли;

// 2. Записать в регистр сведений
НаборЗаписей = РегистрыСведений.ЗаметкиПоПредмету.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Предмет.Установить(ПредметЗаметок);
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Предмет = ПредметЗаметок;
НоваяЗапись.КоличествоЗаметок = КоличествоЗаметок + 1;
НаборЗаписей.Записать();

Правильно:

// 1. Начать транзакцию для пакета из двух операций чтения и записи регистра
НачатьТранзакцию();

Попытка
	// 2. Установить исключительную блокировку на интересующий диапазон записей регистра, 
	// для того чтобы гарантировать, что в момент записи количество заметок не изменилось с момента чтения в каком-либо другом сеансе.
	БлокировкаДанных = Новый БлокировкаДанных;
	ЭлементБлокировкиДанных = БлокировкаДанных.Добавить("РегистрСведений.ЗаметкиПоПредмету");
	ЭлементБлокировкиДанных.УстановитьЗначение("Предмет", ПредметЗаметок);
	ЭлементБлокировкиДанных.Режим = РежимБлокировкиДанных.Исключительный;
	БлокировкаДанных.Заблокировать();
	
	// 3. Прочитать регистр сведений
	Запрос = Новый Запрос(
	"ВЫБРАТЬ РАЗРЕШЕННЫЕ
	| ЗаметкиПоПредмету.КоличествоЗаметок КАК КоличествоЗаметок
	|ИЗ
	| РегистрСведений.ЗаметкиПоПредмету КАК ЗаметкиПоПредмету
	|ГДЕ
	| ЗаметкиПоПредмету.Предмет = &Предмет");
	Запрос.УстановитьПараметр("Предмет", ПредметЗаметок);
	
	Выборка = Запрос.Выполнить().Выбрать();
	
	КоличествоЗаметок = 0;
	Если Выборка.Следующий() Тогда
		КоличествоЗаметок = Выборка.КоличествоЗаметок;
	КонецЕсли;
	
	// 4. Записать в регистр сведений
	НаборЗаписей = РегистрыСведений.ЗаметкиПоПредмету.СоздатьНаборЗаписей();
	НаборЗаписей.Отбор.Предмет.Установить(ПредметЗаметок);
	НоваяЗапись = НаборЗаписей.Добавить();
	НоваяЗапись.Предмет = ПредметЗаметок;
	НоваяЗапись.КоличествоЗаметок = КоличествоЗаметок + 1;
	НаборЗаписей.Записать();
	
	ЗафиксироватьТранзакцию();
Исключение
	// 5. Если при установке блокировки возникла исключительная ситуация из-за того, что регистр уже  заблокирован  в другом сеансе (или по другим причинам),
	// отменить транзакцию и записать сведения об ошибке в журнал  регистрации .
	ОтменитьТранзакцию();
	ЗаписьЖурналаРегистрации(НСтр("ru = 'Заметки'"), УровеньЖурналаРегистрации.Ошибка,,, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
	ВызватьИсключение;
КонецПопытки;

В некоторых случаях, ответственное чтение не требуется в силу решаемой прикладной задачи, например:

В некоторых случаях, ответственное чтение не требуется, так как конкурентная работа с данными маловероятна или полностью исключена, например:

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

Например, в системной транзакции выполняются обработчики модулей объектов и соответствующие им подписки на события:

Подробнее – см. документацию к платформе 1С: Предприятие .

1.3. Если в транзакции производится ответственное чтение данных без их последующего изменения, необходимо установить разделяемую управляемую блокировку (до выполнения чтения). Если же прочитанные данные в дальнейшем модифицируются – следует использовать исключительную блокировку, в противном случае возможно возникновение взаимоблокировки.

Пример установки разделяемой блокировки (без открытия транзакции – в предположении, что ранее уже была открыта системная транзакция):

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

// 2. Прочитать первый объект - приказ 
ПриказОбъект = ПриказСсылка.ПолучитьОбъект();
// 3. Прочитать второй объект –  пользователя  (автора приказа)
АвторПриказа = ПриказОбъект.Автор.ПолучитьОбъект();

Пример установки исключительной блокировки (без открытия транзакции – в предположении, что ранее уже была открыта системная транзакция):

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

// 2. Получить объект для его дальнейшей  модификации 
Объект = ПриказСсылка.ПолучитьОбъект();

// Выполнить блокировку объекта от изменения другими режимами или пользователями
Объект.Заблокировать();
Объект.Реквизит = ...
// 3. Записать измененный объект
Объект.Записать();

Использование чтения вне транзакции

2.1. Не следует завязывать логику механизмов на эффект грязного чтения ( возможность чтения данных незафиксированных транзакций), т.к. его нет в версионных СУБД (PostgreSQL, Oracle database), а прикладные решения должны быть работоспособны на всех СУБД, поддерживаемых платформой. Например, если фоновое задание работает в транзакции, не следует пытаться отслеживать состояние этого задания по изменениям в информационной базе – это не будет работать на версионных СУБД.

2.2. В редких случаях, может быть принято решение о выполнении чтения вне транзакции. Например, из соображений повышения параллельности при многопользовательской работе. *

* Примечание: На СУБД MS SQL попытка чтения вне транзакции может завершится ошибкой "Could not continue scan with NOLOCK due to data movement". Обычно, при возникновении такой ошибки следует попытаться повторно выполнить чтение. При этом число попыток и способ обработки ошибки - отдельный предмет проектирования в каждом конкретном случае.

См. также


Нас находят: 1c 8 2 использование запроса внутри транзакции, 1С грязное чтение регистрсведений, если фоновое задание тогда транзакция, Контроль остатков, наборзаписей записать, попитка внутри транзакции, регистр сведений 1с обработка ошибки, регистр сведений создатьнаборзаписей отбор, тоанзакции на чтение данных


Подписка на новости RSS     Добавьте в закладки Google fusion     Мы в Google+    

 

Мы ВКонтакте

 

Мы на Facebook