Transactions in DataFlex
An AE Group White Paper
Application Engineering Group
Data Access Corporation
Publication date: February 22, 1996
The intention of this paper is to provide a grounding in the concepts of transactions in a database system and how these concepts are applied to DataFlex 3.1. This paper assumes a reasonable working knowledge of programming in DataFlex. The concept of a logical transaction will be explained, along with design issues involved in coding these transactions, as well as some notes on related topics.
What is a transaction?
There are two levels to the answer to this question. To a user/developer, a transaction is the result of entering some data into an application and choosing to save/update the files. To an application-development system such as DataFlex, a transaction is a set of changes to some data files that must either all be saved or all
abandoned (none saved).
What does that mean?
A program can ensure that when users choose to save some data in an application, the data files remain in a known, coherent state regardless of what may happen at any workstation involved in the process. Consider a typical order-entry system with customer files, inventory files, order files, general-ledger files, etc. Imagine a user
enters an order and presses Save, and during the saving process, the computer gets unplugged. Without transaction protection, the data files are then in an unknown state. They may be physically corrupted,
and even if not, it is difficult to know which files have been updated and which have not. You are probably faced with a restore from backup, re-index, and/or other processes that will keep your system non-productive for a significant amount of time. If you have transaction protection on the other hand, either the entire transaction
was saved completely or your data files remain as they were before the Save key was pressed. Either way, no other user of your system was affected and there is no system-wide down time. Even if it was the server that crashed, you can probably be up and running very quickly with no loss of data.
What are some of the design issues?
By default, DataFlex starts a transaction when it does a reread or a lock and completes the transaction when it does the corresponding unlock. This is better than no protection, but may be not much better, depending on how it is coded.
Consider the following block of updating code:
... user presses save
...update customer files
...update inventory files
...update general ledger files
... control returns to user
If a machine failure occurs during execution of these updates, the default transaction system will treat each reread . . . unlock block as a transaction, and will abort the one executing at the time of the failure.
The trouble is, we will not know which one. If we were to place a begin_transaction and end_transaction around the entire block of code shown, then we would only have one logical transaction. This means
that either everything will be updated or nothing. The files, therefore, remain in a known state because we can simply check whether an order exists or does not, it cannot be half-processed.
To take full advantage of the transactional ability of DataFlex, provide begin_transaction and end_transaction around blocks of update code such as that shown to form logical transactions. The commands
discussed here apply to both procedural and object-oriented programs but it is important to note that if you are using OOP style DataFlex the datasets do the begin/end_transaction calls for you and you dont need to code this. It is also important to note that a program must not chain in the midst of a logical transaction. Attempting to chain while a transaction is incomplete will trigger an error report. If you have applications that do this, you will have to merge some existing code so that all parts of each logical transaction are contained within the same .flx program.
The other critical area of design is understanding how the transaction system performs retries of a transaction. If during a transaction a transaction error is generated then DataFlex will retry the transaction a configurable number of times. The way this is done is by calling the transaction system to rollback all files involved in the transaction and then performing basically a GOTO to the start of the transaction (the begin_transaction, lock or reread). The code is then RE-EXECUTED from that point. It is very important to realize that the datafiles are
rolled back but that nothing else is. If you changed variables, wrote data to a text log file, etc. inside the transaction then this code would be re-executed (by default up to 15 times).
The way to design your transaction code is to use another set of variables (local variables if possible) rather than modifying global variables in such a way that the code can be executed multiple times with the correct result.
The default transaction mode of DataFlex files is client_atomic, which enables your program to maintain transactional integrity under all circumstances but a crash of the file server. This level of protection is
provided regardless of whether the program is run with protection against server crashes (see below).
How can I protect against server crashes?
You need to make your data files transactional. To do this, you must either use a client/server database, via the appropriate drivers, for your files, such as the DataFlex Server or Sybase server products, or if you are using Novell NetWare, use its Transaction Tracking System (TTS). If you do this, you can also set every data file involved in transactions to server_atomic with DataFlexs File Definition Utility.
Is that it?
Yes, that is all there is to taking advantage of the security made possible by transaction protection now available in DataFlex 3.1
Technical Questions and Answers
Q: I have a program from 3.05 that I use with no rereads (single-user mode) and when I try to update it with 3.1, I get Error 4155, even if I set DFREREADOPT. Why?
A: In DataFlex 3.1, the default transaction mode of files is client_atomic, so if you open the file with 3.1 it is by default transactional. A transactional file cannot be updated without rereads regardless of DFREREADOPT, because reread and unlock provide begin_transaction . . . end_transaction markers. You must set the file to
Transaction Type none using the 3.1 DFFILE or DFADMIN. It is important to note that data sets now require transactional files, files that are to be used in data sets must be transactional. Data sets now
use the database driver to do rollbacks rather than doing them themselves. Attempting to assign a main file to a data set that is non-transactional will cause the data set to generate an error and the
data set will not initialize.
Q: Does NetWares TTS slow my system down or take up disk space?
A: TTS will affect the speed of database operations, but the speed difference is minor and certainly worth the benefits that TTS provides. In most cases, you should be unable to perceive any speed difference at all. TTS will consume disk space only on the SYS volume of your file server. This is where TTS keeps its backout
information. The server will eventually clear this space, but by default, it keeps the backout data for about an hour (you can shorten this period by configuring your server). The amount of space can be significant. TTS can use up to approximately 100K per transaction for regular database operations. This means that you may need to allocate (keep available) quite a few megabytes on your servers SYS volume. The server will normally still run if all the space is used up, but you will lose the protection of TTS while there is no free space for backout data. On occasions the file server (in earlier versions on Novell) may even crash if you run out of space for TTS backout but this is uncommon.
Q: What does client_atomic do? Does it mean that files on my local hard disk have transaction protection?
A: Client_atomic is the default transaction mode for DataFlex files. DataFlex processes transactions entirely in memory. This provides no transaction protection against crashes of the computer(s) that controls the disk drive(s) involved. It does behave like a database that has transaction protection, which means that you can write just one set of code and assume that the database you use has transaction-rollback capability. To get true transaction protection, you have to have your data files on some sort of server and not on your local hard disk.
Q: How do I decide what is a logical transaction?
A: A logical transaction is simply all the database operations that make up a complete operation in your application, such as booking an order or deleting a customer and all their related records. The rule
is: either everything in a logical transaction must get saved, or it all must be reversed out. You should look for blocks of updates that occur when a user says go. This would typically include all the database updates that occur from the time a user presses Save or Delete right up until the application is waiting for user input again.
There is a good chance that all the database operations that occur in such cases are one logical transaction.
Q: What platforms support TTS?
A: The only server that supports TTS is Novell. Most of the clients for Novell support TTS but TTS is a Novell technology and is not available for any other server environment.
Q: What is the difference between using reread/unlock and begin/end_transaction?
A: If a transaction fails (after the set number of retries) and you are using reread/unlock then you will receive an error and execution will resume at the next line after the one that caused the error. If you were using begin/end_transaction then you will receive an error and execution will resume at the next line after the end_transaction.
For further information on this subject, we recommend reading Novells NetWare Server Administration documentation, as well as the Data Access Application Engineering Groups White Paper
entitled DataFlex & NetWare.
Data Access Worldwide
14000 SW 119 Ave
Miami, FL 33186
Domestic Sales: 800-451-3539
Newsgroup Server: news.dataaccess.com
Data Access Worldwide - Asia Pacific
Suite 5, 333 Wantirna Road, Wantirna VIC 3152 Australia
Phone: +61 3 9800 4233 f: +61 3 9800 4255
Data Access Worldwide - Brasil
Av.Paulista, 1776 - 21st.Floor
São Paulo -SP - Brazil
Data Access Worldwide - Europe
7553 AE Hengelo
Telephone: +31 74 - 255 56 09
Fax: +31 74 - 250 34 66
Data Access Technical Knowledge Base http://www.dataaccess.com/kbase
Many answers to technical problems can be found online in the Data Access Technical Knowledge Base. Here, you can access the same live data that Data Access Worldwide technical support and development staff use to enter and track technical articles.
This document is property of Data Access Corporation. With credit to Data Access Corporation for its authorship, you are encouraged to reproduce this information in any format either on paper or electronically, in whole or in part. You may publish this paper as a stand alone document within your own publications conditional on the maintenance of the intent, context, and integrity of the material as it is presented here.
DataFlex is a registered trademark of Data Access Corporation.
NO LIABILITY FOR CONSEQUENTIAL DAMAGES
To the maximum extent permitted by applicable law, in no event shall Data Access Corporation be liable for any special, incidental, indirect, or consequential damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or any other pecuniary loss) arising out of the use of or inability to use any information provided in this document, even if Data Access Corporation has been advised of the possibility of such damages. Because some states and jurisdictions do not allow the exclusion or limitation of liability for consequential or incidental damages, the above limitation may not apply to you.