Control the size of a transaction
- Last Updated: April 25, 2024
- 4 minute read
- OpenEdge
- Version 13.0
- Documentation
You have already learned which statements start a transaction automatically. To summarize, these are:
-
FOR EACHblocks that directly update the database -
REPEATblocks that directly update the database - Procedure blocks or user-defined functions that directly update the database
-
DOblocks with theON ERRORorON ENDKEYqualifiers (which you'll learn more about later) that contain statements that update the database
You can also control the size of a transaction by adding the TRANSACTION keyword
to a DO, FOR EACH, or REPEAT block.
This can force a transaction to be larger, but because of the statements
that start a transaction automatically, you cannot use it to make
a transaction smaller than ABL otherwise would make it.
Take another look at the update procedure saveOrder, in the sample logic procedure h-OrderLogic.p, to see how transaction blocks are affected by changes to the procedure.
As written, there is a DO TRANSACTION block around the whole update of both
the Order and any modified OrderLines:
|
Since DO blocks do not have the block transaction property,
any changes made in the DO block (Order update block)
scope to the containing transaction block, in this case the DO TRANSACTION block.
Any errors that occur within the DO block cause
the entire transaction to be backed out.
FOR EACH
ttOline starts a new subtransaction for each iteration. If an
error occurs within the FOR EACH block, only the change made
for that iteration is backed out. Any changes for any previous iterations, as well as any
changes made in the DO block, are committed to the database.
To verify this, generate a listing file the same way you did previously:
When you run this COMPILE statement, your listing file
tells you, among other things, where all the transactions begin
and end. This is very valuable information. You should always use
a listing file in any complex procedure to make sure that your record
scope and transaction scope are as you intended.
OrderLine record to undo the Order updates as
well, then FOR EACH OrderLine should be rewritten as
follows:
|
DO
TRANSACTION block and cause that block to undo, thus undoing the entire
transaction.Back to the original code and taking a look at the listing file, you can see that the
DO TRANSACTION block is a top-level block within its procedure, marked with
a 1. The DO block inside it, where the Order is
actually updated, is block level 2:
|
Further down, you can see that the FOR EACH block that
operates on the OrderLines is also a nested
block, at level 2 within the main DO TRANSACTION block:
|
Now if you look at the end of the file, you see a summary of all the blocks. Here is an excerpt from that part of the listing. It shows that the procedure blocks for the internal procedures fetchOrder and saveOrder are not transaction blocks:
|
This is a good thing. You never want your transactions to default to the level of a procedure, because they are likely to be larger than you want them to be. This means that record locks are held longer than necessary and that more records might be involved in a transaction than you intended.
Next you see that the AVM identifies the first DO block at line 138 as a transaction block. This is because it has an explicit
TRANSACTION qualifier on it. The nested DO block two lines later is not a transaction block because a
DO block by itself does not mark a transaction.
The FOR EACH block at line 157 is also
marked as a transaction block:
|
What does this mean? Is this really a separate transaction? The
answer is no, because the FOR EACH block is nested
inside the larger DO TRANSACTION block. This code
tells you that the FOR EACH block would be a transaction
block (because this is the nature of FOR EACH blocks
that perform updates). However, because it is nested inside a larger
transaction, it becomes a subtransaction. The AVM can back
out changes made in a subtransaction within a larger transaction
when an error occurs, and you can also do this yourself, as described
in the Subtransactions.