Scope: managed applications, mobile applications, and ordinary applications.
1. General recommendations on the use of transactions upon reading data
Scope (details): a managed application, an ordinary application.
1.1. If reading of infobase data must be mission-critical, read it in a transaction where managed locks are preset. Any reading is treated as mission-critical if its results are used to change an infobase or make decisions. For example, mission-critical data reading is required in the following cases:
-
Data is read upon posting to generate records later.
-
Data is read to integrally transfer it to another system, for example, "Client bank" or similar.
-
Objects are subject to bulk processing upon data restructuring in handlers of deferred or seamless infobase update (*). * Note: before reference objects are modified, it is recommended that you set pessimistic object locks for them .
Incorrect:
// 1. Read the information register Query = New Query( "SELECT ALLOWED | SubjectNotes.NumberOfNotes AS NumberOfNotes |FROM | InformationRegister.SubjectNotes AS SubjectNotes |WHERE | SubjectNotes.Subject= &Subject"); Query.SetParameter("Subject", NotesSubject); Selection = Query.Execute().Select(); NumberOfNotes = 0; If Selection.Next() Then NumberOfNotes = Selection.NumberOfNotes; EndIf; // 2. Write to the information register RecordSet = InformationRegisters.SubjectNotes.CreateRecordSet(); RecordSet.Filter.Subject.Set(NotesSubject); NewRecord = RecordSet.Add(); NewRecord.Subject = NotesSubject; NewRecord.NumberOfNotes = NumberOfNotes + 1; RecordSet.Write();
Correct:
// 1. Start a transaction for a package of two register read and write operations BeginTransaction();
Attempt // 2. Set an exclusive lock for a register record range // to ensure that at the time of writing the number of notes remains unchanged since they were read in another session. DataLock= New DataLock; DataLockItem = DataLock.Add("InformationRegister.SubjectNotes"); DataLockItem.SetValue("Subject", NotesSubject); DataLockItem.Mode = DataLockItem.Exclusive; DataLock.Lock(); // 3. Read the information register Query = New Query( "SELECT ALLOWED | SubjectNotes.NumberOfNotes AS NumberOfNotes |FROM | InformationRegister.SubjectNotes AS SubjectNotes |WHERE | SubjectNotes.Subject= &Subject"); Query.SetParameter("Subject", NotesSubject); Selection = Query.Execute().Select(); NumberOfNotes = 0; If Selection.Next() Then NumberOfNotes = Selection.NumberOfNotes; EndIf; // 4. Write to the information register RecordSet = InformationRegisters.SubjectNotes.CreateRecordSet(); RecordSet.Filter.Subject.Set(NotesSubject); NewRecord = RecordSet.Add(); NewRecord.Subject = NotesSubject; NewRecord.NumberOfNotes = NumberOfNotes + 1; RecordSet.Write(); CommitTransaction(); Except // 5. If an exception occurred upon locking since the register is already locked in another session (or for any other reason), // cancel the transaction and write error details to the event log. RollbackTransaction(); WriteEventLog(NStr("en = "Notes'", CommonClientServer.DefaultLanguageCode()), EventLogLevel.Error,,, DetailErrorDescription(ErrorInformation())); Raise; EndTry;
|
In some cases, mission-critical reading is not required due to the application task being performed. For example:
- Data retrieval by dynamic lists
- Search
- Generation of most reports
There are cases when mission-critical reading is not required as parallel operations with data are unlikely or excluded. For example:
-
Access of conditionally persistent information. For example, reading the RegulatoryAccountingCurrency constant or accessing the accounting policy.
-
Operations performed in exclusive mode only. For example, in procedures of update and initial data filling of the infobase.
-
Actions taken on data that can be accessed by a single user only. Concurrent actions on this data are unlikely or excluded.
For example, personal data that is stored broken down by users.
-
A mobile application where concurrent actions with data are unlikely or excluded.
1.2. In most cases, upon reading data in event handlers associated with data modification, the whole handler code is executed as part of a system transaction opened by the platform, so it is not required to explicitly open a new transaction.
For example, object module handlers and related event subscriptions are executed in a system transaction:
For more information, see 1C:Enterprise documentation.
Scope (details): a managed application, an ordinary application.
2. Selection: an exclusive or a shared lock.
2.1. If mission-critical data reading is performed in a transaction with further modification of that data, set an exclusive managed lock (before reading). Otherwise, a deadlock might occur.
Example of an exclusive lock (without opening a transaction on the assumption that a system transaction is already open):
// 1. Setting an exclusive lock to trigger mission-critical reading of an object to change it later Lock = New DataLock; LockItem = Lock.Add("Catalog.Orders"); LockItem.SetValue("Ref", OrderRef); LockItem.Mode = DataLockMode.Exclusive; // It may not be specified as Exclusive is set by default Lock.Lock();
// 2. Getting the object for its further modification Object = OrderRef.GetObject();
// Locking the object from changes by other modes or users Object.Lock(); Object.Attribute= ... // 3. Write the modified object Object.Write();
2.2. If mission-critical reading of data is performed in a transaction without its further modification (for example, to generate records), set a shared lock for data to read and an exclusive lock for data to change.
Example of a shared lock (without opening a transaction on the assumption that a system transaction is already open):
// 1. Setting a shared lock for mission-critical reading of several related objects Lock = New DataLock; LockItem= Lock.Add("Catalog.Orders"); LockItem.SetValue("Ref", OrderRef); LockItem.Mode= DataLockMode.Shared; Lock.Lock();
// 2. Reading the first object, which is an order OrderObject = OrderRef.GetObject(); // 3. Reading the second object, which is a user (an order author) OrderAuthor = OrderObject.Author.GetObject();
|
See also: