Understanding Concurrency Control

Objectives

After completing this lesson, you will be able to:
  • Describe pessimistic concurrency control (locking).
  • Enable optimistic concurrency control.

Concurrency Control Concepts

The comparison between Pessimistic and Optimistic concurrency control

Concurrency control prevents concurrent and interfering data access of different users. It ensures that data can only be changed if data consistency is assured.

RESTful applications are designed to be usable by multiple users in parallel. If more than one user has transactional database access, you must make sure that every user only executes changes based on the current state of the data so the data stays consistent. In addition, you must make sure that sure that users do not change the same data at the same time.

There are two approaches to regulate concurrent writing access to data. Both of them must be used in the ABAP RESTful Application Programming Model to ensure consistent data changes.

Pessimistic Concurrency Control

Pessimistic concurrency control prevents simultaneous modification access to data on the database by more than one user.

Pessimistic concurrency control is done by exclusively locking data sets for the time that a modification request is executed. The data set that is being modified by one user cannot be changed by another user at the same time by using a global lock table.

The lifetime of such an exclusive lock is tied to the session life cycle. The lock expires once the lock is actively removed after the successful transaction or with the timeout of the ABAP session.

In managed scenarios, the business object framework assumes all locking tasks. You do not have to implement the locking mechanism in that case. If you do not want the standard locking mechanism by the managed business object framework, you can create an unmanaged lock in the managed scenario. In unmanaged scenarios, the application developer has to implement the method for lock and implement the locking mechanism. It is covered later in this course.

Optimistic Concurrency Control

Optimistic concurrency control enables transactional access to data by multiple users at the same time, while avoiding inconsistencies and unintentional changes of already modified data.

The approach of optimistically controlling data relies on the concept that every change on a data set is logged by a specified field, called the ETag field. Often, the ETag field contains a timestamp, a hash value, or any other versioning that precisely identifies the version of the data set.

Concurrency control based on ETags does not lock the data set. Instead, it refuses data changes if the ETag value on the database changed since the client last read the data set. This mechanism is independent from ABAP sessions and data sets are not blocked to be used by other clients. It is important for RESTful protocols like OData, because such protocols are always stateless and each request is handled in a different session.

Pessimistic Concurrency Control

A visual representation of Locking During UPDATE Operation

Technically, pessimistic concurrency control is ensured by using a global lock table. Before data is changed on the database, the corresponding data set receives a lock entry in the global lock table.

Every time a lock is requested, the system checks the lock table to determine whether the request collides with an existing lock. If this is the case, the request is rejected. Otherwise, the new lock is written to the lock table. After the change request has been successfully executed, the lock entry on the lock table is removed. The data set is available to be changed by any user again.

The lifetime of such an exclusive lock is tied to the session life cycle. The lock expires once the lock is actively removed after the successful transaction or with the timeout of the ABAP session.

The example illustrates how the lock is set on the global lock table during an UPDATE operation. The client that first sends a change request makes an entry in the global lock table. During the time of the transaction, the second client cannot set a lock for the same entity instance in the global lock tables and the change request is rejected. After the successful update of client 1, the lock is removed and the same entity instance can be locked by any user.

Optimistic Concurrency Control

ETag Check in UPDATE Operation

When optimistic concurrency control is enabled for a RAP business object, the OData client reads the current ETag value with every read request and sends this value back with every modifying operation.

On each ETag relevant operation, the value the client sends with the request is compared to the current value of the ETag field on the database. If these values match, the change request is accepted and the data can be modified. At this point, the business object logic changes the value of the ETag field.

In the example, both OData clients read the data with the value 'X' in the ETag field. When Client 1 sends an update request with ETag value 'X', this request is accepted because the ETag field value 'X' matches the value on the database. During the update of the data, the ETag field value is changed to a different value. In our example, the new value is 'Y' .

The ETag mechanism ensures that the client only changes data with exactly the version the client wants to change. In particular, it is ensured that data an OData client tries to change has not been changed by another client between data retrieval and sending the change request. On modifying the entity instance, the ETag value must also be updated to log the change of the instance and to define a new version for the entity instance.

In the example the update request of Client 2 is rejected because it is sent with ETag field value 'X'. By comparing this value to the current value on the database, the business object logic sees that a concurrent modify access took place and that Client 2 is operating on an outdated version of the data.

ETag Definition and Implementation

Activation of ETag handling in RAP

In RAP, ETag handling is activated by adding etag master to the behavior definition of the root entity. The keyword master is followed by the name of a field that is part of the business object entity. You must make sure that the value of this field is changed during every modify operation on this entity.

Note

In business objects consisting of several entities (composite BOs), sub entities can either be their own ETag masters or they can be defined with addition etag dependent. With this addition, instances of that sub entity are not protected with an ETag field of their own. Instead, they refer to an ETag master entity further up the hierarchy, for example the root entity..

To expose the ETag for a service specification in the projection layer, the usage of the ETag field has to be declared in the behavior definition on projection layer with the use etag addition of the define behavior statement. The ETag type (master or dependant) is derived from the underlying behavior definition and cannot be changed in the projection behavior definition. Once the ETag is exposed to the service, clients include the ETag value in any relevant request.

Recommended ETag field in managed scenario

The ETag mecahnism only works properly if the ETag field receives a new value whenever the data set of the entity instance is changed or created. That means, for every modify operation, except for the delete operation, the ETag value must be uniquely updated.

In managed scenarios, the recommended way to establish the ETag mechanism is a timestamp field of type abp_lastchange_tstmpl and annotated with @Semantics.systemDateTime.LastChangedAt: true. With this annotation, the RAP BO runtime automatically stores the current timestamp in this field when it changes a given data set.

Note

If you choose an element as an ETag field that is not automatically updated, you have to implement the update manually, for example in a determination, and ensure that the code is executed during every modify operation and assigns a new value.

Annotation @Semantics.systemDateTime.LastChangedAt: true is not the only annotation that triggers automatic updates of fields by the framework. Here are some more examples:

  • @Semantics.user.createdBy: true
  • @Semantics.systemDateTime.createdAt: true
  • @Semantics.user.lastChangedBy: true

But keep in mind that none of those annotations come with a guarantee that the value changes in any update. Therefore, fields annotate like this do not make good ETag fields.

Enable Optimistic Concurrency Control

In this exercise, you enable optimistic concurrency control in your business object. To do this, you specify one view element as the ETag field and make sure that the run time changes the value of this element during every write access to the business object.

Note

In this exercise, replace ## with your group number.

Solution

Repository Object TypeRepository Object ID
CDS Data Definition (Model)/LRN/437B_R_TRAVEL
CDS Behavior Definition (Model)/LRN/437B_R_TRAVEL
CDS Behavior Definition (Projection)/LRN/437B_C_TRAVEL

Task 1: Enable Automatic Update of Administrative Fields

Make sure that the runtime automatically updates the administrative fields ChangedAt and ChangedBy when writing changes to the database.

Steps

  1. In the definition of your data model view Z##_R_Travel, add the annotation @Semantics.systemDateTime.lastChangedAt: true to the ChangedAt view element.

    1. Adjust the code as follows:

      Code Snippet
      123
      @Semantics.systemDateTime.lastChangedAt: true changed_at as ChangedAt, changed_by as ChangedBy
  2. Add annotation @Semantics.user.lastChangedBy: true to the ChangedBy view element.

    1. Adjust the code as follows:

      Code Snippet
      1234
      @Semantics.systemDateTime.lastChangedAt: true changed_at as ChangedAt, @Semantics.user.lastChangedBy: true changed_by as ChangedBy
  3. Activate the data definition.

    1. Choose Activate or press Ctrl + F3.

  4. Execute your ABAP class ZCL_##_EML as a console application again to set the description of one of your flights.

    1. Open the source code of the class, and press F9 to execute it.

  5. Use the Data Preview tool to confirm that the ChangedAt and ChangedBy view elements return updated values.

    1. Right-click anywhere in the definition of your data model view Z##_R_Travel and choose Open WithData Preview.

      Result

      In the data set that you changed with EML, the values displayed in columns ChangedAt and ChangedBy must be different than in the other data sets.

Task 2: Define ETag Field

Enable optimistic concurrency control for your business object by making a suitable view element the ETag field of your entity. Then expose the ETag definition to the OData service.

Steps

  1. In your behavior definition for the data model view Z##_R_Travel, add the etag master addition, followed by the field name ChangedAt.

    1. Adjust the code as follows:

      Code Snippet
      12345
      define behavior for Z##_R_Travel alias Travel persistent table z##_travel lock master authorization master ( instance ) etag master ChangedAt
  2. Activate the behavior definition.

    1. Press Ctrl + F3 to activate the development object.

  3. In your behavior projection, that is, in the behavior definition for the projection view Z##_C_Travel, add the use etag addition.

    1. Adjust the code as follows:

      Code Snippet
      1234567
      define behavior for Z##_C_Travel //alias <alias_name> use etag { use create; use update; use delete; }
  4. Activate the behavior projection.

    1. Press Ctrl + F3 to activate the development object.