Technical Articles
The SAP LUW in ABAP Cloud
Preface
This blog describes the differences between classic ABAP programming and ABAP Cloud programming with regards to the SAP Logical Unit of Work (SAP LUW) [1] and the ABAP RESTful application programming model (RAP). It helps to understand how database updates work and what developers must consider avoiding data inconsistencies during database updates.
Classic ABAP Programming
In typical business applications, the data is changed, further changes are derived, and the data is verified. If the resulting state based on these changes is consistent from an application point of view, the changes are finally committed to the database. All changes made are committed with one atomic database transaction following the ACID [2] paradigm.
To achieve this, SAP provides the SAP Logical Unit of Work (SAP LUW) for classic ABAP programming. As the database is the central resource and can become a bottleneck, the processing and handling is done on the ABAP application server. Therefore, the data changes are not directly written to the database but kept in local temporary tables or buffers and are then jointly written to the database, either directly or via SAP update task. The SAP LUW terminates by calling COMMIT WORK if all changes were done successfully, or by calling ROLLBACK WORK if not.
Processing the COMMIT WORK statement includes:
- the update task processing.
- a database commit of the primary database connection.
- starting of further asynchronous processing (e.g., via background RFCs) or registering on the transaction end events to clean up the buffers and prepare for the next SAP LUW in the same ABAP session.
When a ROLLBACK WORK statement is processed all changes are discarded, the current SAP LUW is terminated and a new one is opened.
Why is there an Update Task in classic ABAP programming?
The recommendation for classic ABAP programming is to always use update task function modules to perform modifying database operations, due to mainly three reasons:
- In the past, database updates had a significant impact on the end-user performance. The update task offered an option to perform the (real) actual database changes asynchronously. This helped improving the perceived end-user performance.
- Data consistency was not always given because proper isolation of database modifications was not available for all databases supported by SAP at that time. This means, that uncommitted database modifications were visible to other transactions although not finally committed.[3]
- The SAP LUW is confirmed with an explicit COMMIT WORK But, as will be explained in the next section, the ABAP Platform sometimes invokes implicit database commits on the primary database connection. If data was already written before to the database, then the implicit database commit would result in multiple database transactions (database LUW) within one SAP LUW which violates the ACID paradigm.
Why are there implicit database commits?
The ABAP Platform scales via load balancing and multiple application server instances. In the cloud, these can be added and removed on demand. The number of work processes of an ABAP application server is limited, and their usage optimized. If a work process needs to wait (idle), e.g., when waiting for user interaction or remote connection, the work process is released for a different workload. This is done by saving (also called rolling-out) the current workload context and releasing the resources. This approach requires a database commit. It also explains why a synchronous RFC (sRFC), calling a WAIT statement (e.g., for asynchronous tasks via asynchronous RFC (aRFC)) or the invocation of an HTTP request via HTTP client leads to a database commit – as it might take a while until these requests return and the program can continue, and it is usually not known upfront how long it takes.
What about secondary database connections?
Database modifications and commits – on service connections or via secondary database connections – are allowed within the SAP LUW. These connections are usually used by technical components, e.g., for fetching the next bunch of numbers of a buffered number range, or for persistent caches, traces, logs or similar.
ABAP Cloud Development Model
In the ABAP Cloud development model, the classic update task is not offered anymore. The reasons for the usage of an update task, as mentioned in the chapter before, are not applicable anymore:
- Writing directly to the database tables is no bottleneck anymore, as database processing on SAP HANA is much faster.
- SAP HANA as the only supported database provides full isolation, thus preventing dirty read.
- Implicit database commits are no issue anymore if database modifications are triggered as late as possible, ensuring that afterwards no database commit except via COMMIT WORK is invoked.
Nevertheless, data changes are still done in the buffers of the application server. The data is enriched, verified, and finally saved to the database.
It cannot be prevented that implicit database commits happen before saving the data to the database, as calling remote services (e.g., via sRFC or HTTP client) is still possible. Consequently, modifying database operations are only allowed at the end of the SAP LUW.
Furthermore, once the end of the SAP LUW is reached and the modifying database operations are invoked, all operations that lead to an implicit database commit are not allowed anymore, as these would disrupt the consistency and atomicity (ACID).
Obviously, the explicit database commit on the primary database connection is only allowed to finally terminate the SAP LUW, but not before. Also, the pattern to start further asynchronous processing is still needed and valid (e.g., via bgRFC).
This requires to strictly follow these rules from application development to avoid inconsistencies due to multiple database LUWs.
How is this handled in the ABAP RESTful Application Programming Model (RAP)?
Compared to classic ABAP programming, RAP is a more advanced application programming model with further abstraction. RAP controls the transactions (ABAP LUW) and provides an orchestration with clearly defined phases, namely:
- the interaction phase,
- the early-save phase,
- the late-save phase followed by a cleanup.
The RAP transaction model is described in more detail in the RAP documentation
(The RAP Transactional Model for the SAP LUW).
Based on this transaction model, the rules, and guidelines of the SAP LUW can be manifested by runtime checks. With these checks in place, you can avoid data inconsistencies or race conditions.
The following violations will always lead to a runtime error in a RAP context:
- Explicit use of COMMIT WORK or ROLLBACK WORK statements, as the transaction handling and database commit is exclusively handled by RAP.
- Calling the update or background task (bgRFC) [4] in the interaction phase or early-save phase.
Some other operations only lead to runtime errors, if the RAP behavior definition is implemented in ABAP for Cloud Development and the strict(2)-mode [5] is applied:
- Invoking authorization checks in the early-save or late-save phase.
- Modifying database operations in the interaction phase or early-save phase.
- Raising business events in the interaction phase or early-save phase.
- (Implicit or explicit) database commits for the primary database connection in the late-save phase.
Conclusion
The ABAP RESTful Application Programming Model supports you in following the rules to avoid issues with transactional consistency caused by modifying statements or database commits in the wrong sequence / phase.
Feel free to share your feedback or thoughts by commenting this BLOG.
With the information provided here you also get an understanding on how and where BAPIs can be used in RAP as described in Using BAPIs in RAP provided by my colleague Marcel Hermanns.
Follow for more via Renzo Colle.
[1] A sequence of programming steps and data updates, whose database changes are updated within a single database commit.
[2] ACID (atomicity, consistency, isolation, durability), check also https://en.wikipedia.org/wiki/ACID.
[3] Also known as dirty read.
[4] Not available in ABAP Platform Cloud, work in progress.
[5] The strict mode adds additional consistency checks during development so that to the RAP behavior definition is developed life cycle stable.
Nice. The only problem is that Restful ABAP (RAP) isn't restful anymore that way.
Not sure I understand that comment. The BLOG describes the behavior of an atomic transaction (LUW) in ABAP, e.g. initiated by a single OData request / change set.
Renzo Colle This is very good concept. I have been working in RAP for last 1 year. I was wondering about the concepts for the update events and how it works. It is giving the clear understanding about RAP. Will keep in mind while working further.
Hi Sagar, thanks for the feedback.
Thanks a lot Renzo Colle ! I believe this is a very relevant topic.
It would also be interesting to know if there are differences in LUW when operating ABAP Cloud embedded in SAP S/4HANA on-prem or in SAP BTP.
To me, it would be interesting exploring SAP LUW in mixed deployments (cloud/on-prem) and in mixed software architectures (e.g. RAP/non-RAP) because often present these days in real-life scenarios.
Kind regards,
Sergio
Hi Sergio, thanks for the feedback.
In fact there is no difference in embedded scenario or even on premise if you use "ABAP for Cloud Development" as ABAP language version. The difference is only if you switch to "Standard ABAP" which is not possible in SAP BTP, ABAP environment. In this case certain violations detected by RAP do not lead to a runtime error, but are just logged for analysis. Further here also currently not available features in ABAP Cloud can be used, e.g. update task function modules or RFC functions. For these it is ensured similarly that they are only called in the correct phase.
Thus, in mixed scenarios where also non-RAP parts are running the same rules are applied (and should have been even before), so RAP just makes them more visible.
Thanks, Renzo!
Is it possible to cover these complex topics also within some DMO flight model samples? E.g. what Marcel pointed out: REPORTED and FAILED can also be filled in the late save, by using the save handler cl_abap_behavior_saver_failed
Hi Stephan, thanks for the feedback.
I will check with my colleagues if there is already a scenario in place or planned.
Thank you Renzo for elaborating the RAP LUW details. I have 2 questions after reading the blog:
1) You mentioned "Writing directly to the database tables is no bottleneck anymore". Does this mean all the managed BO implementation utilize the direct DB modifications? And if yes, is this the guideline moving forward?
2) You also mentioned "data changes are still done in buffers of app server". Is the buffer handling similar to what was used in BOPF framework? There the buffer handling was taken care by the framework. But here in the official unmanaged RAP example of /DMO/Flight, I see the buffers are mainly the abap internal tables/abap variables to store the data during interaction phase. So is it safe to assume a similar approach is happening internally in a managed scenario too or is there a separate buffer handling framework for managed scenario?
Hi Sujin, thanks for the feedback. Here a short answer to your questions:
Hi Renzo,
Regarding the #2 - Thank you for confirming on the BOPF framework for managed use case.
For unmanaged use case, is the recommended approach to implement buffer handling way its shown in the official example /DMO/FLIGHT_U where the interaction phase data is stored in the abap internal tables and the later used by SAVE phase or can we use BOPF framework for unmanaged buffer handling too?
Regards,
Sujin
For UNMANAGED the assumption is that there is already legacy functionality with transactional buffers and application logic. Therefore building a secondary buffer does not really make sense. In such a case it is better to use MANAGED and ensure interoperability with a still running legacy application (e.g. WebGUI or similar) via UNMANAGED LOCK, UNMANAGED SAVE / ADDITIONAL SAVE etc.
Hello Renzo,
Thanks for this well-detailed post, it puts things in perspective.
But my question to you would be that in real-life scenarios we have to use the BAPIs only, as creating a RAP business object directly on SAP standard tables, I assume, is not good or even recommended.
And in most of the requirements, we have to post multiple BAPIs in a single process. Considering that, we have to then resort to the 'BAPI_TRANSACTION_COMMIT' in between the BAPI calls which, is NOT ALLOWED in RAP LUW for which the workaround is to use an aRFC and then perform all the actions inside aRFC FM and then wait for it to finish to send back the resulting error or success messages back to the front end using "reported" table.
is the aRFC approach recommended by SAP and if not then how do we handle these complex scenarios inside RAP development guidelines.
Hi Piyush,
thanks for your question. Regarding the integration of BAPIs I recommend to check the linked blog post of of colleague Marcel Hermanns. BAPIs are not transactional, so calling multiple BAPIs within one SAP LUW is like calling all of them independently in separate SAP LUWs, except the all are committed together. If you need to commit in between even because the BAPI calls rely on each other and need the (peristed) data of the previous BAPI call you need to have very good error handling and restartability / cleanup in place as you never can be sure all calls are finally committed. Depending on the use case of your RAP implementation you may use an sRFC (in the interaction or early save phase, e.g. if you fire the BAPIs during an action implementation or during finalize) or (rather recommended) to invoke a bgRFC during save based on the data / operations invoked in the RAP behavior definition and in there do what you need to do, i.e. call the BAPIs.
Kind regards,
Renzo