Transactions

The Transaction shape is used to draw a boundary around a process flow fragment and then make assertions about the transacted behavior of the flow enclosed by the shape. The subject matter relating to transactions is large, and it is crucial that you understand the issues involved so that you can effectively translate your business process into a reliable and predictable XLANG schedule. Even if the subject of transactions were not new to you, it would be beneficial to augment your study with a book devoted to this subject matter. This section introduces the Transaction shape and describes the behavior of transactions in an XLANG schedule. Chapter 10 delves further into the implementation aspects for transactions in XLANG schedule.

Each Transaction shape provides a virtual Begin and a virtual End point for the business process that it encloses. The enclosed business process is called the body of the transaction. The business process outside the Transaction shape can treat the body of a transaction as if it were a single Action—that is, with a single path in and a single path out. The business process inside the Transaction shape is connected to these entry and exit points. The internal process flow cannot contain an End shape as a termination point; however, it may contain an Abort shape, in which case, the enclosing transaction is aborted—more on this later. However, an End shape may be present within a transaction to delimit the body of an enclosed While shape.

Transactions in an XLANG schedule are essentially of two types: long-running and short-lived. The BizTalk documentation mentions a third type called the timed transaction type; however, such a transaction type is a long-running transaction that is automatically aborted when the allotted time expires. The familiar database transaction falls in the short-lived category.

Short-Lived Transactions

Short-lived transactions have the familiar ACID properties of a transaction. An isolation level for such transactions can be specified by the programmer in the transaction configuration dialog. These types of transactions also are called DTC style transactions because they usually use the services of Microsoft Distributed Transaction Coordinator (MS DTC) to manage transactions that span multiple resource managers (such as databases). DTC uses the two-phase commit protocol to ensure that transactions are atomic and durable across all enlisted systems in the transaction—see more on these terms in the ACID sidebar later in the chapter.

You can specify that a short-lived transaction be re-attempted a certain number of times if it fails—the Retry count property of the Transaction shape. The time duration between retries also can be specified. This is done by setting the Backoff time property of the Transaction shape. These two properties are not available for long-lived transactions.

The backoff time is computed exponentially. For example, a backoff time of 10 seconds translates into retry intervals of 10, 10**2, 10**3, and so on. With a 10-second backoff time and 3 retries, the last retry occurs roughly 17 minutes later.

Figure 9.7 shows the default Transaction Properties dialog box.

Figure 9.7. The Transaction Properties dialog.


Figure 9.7 shows that a transaction can be named, and the transaction type can be specified. Based on the transaction type, you can set various options. The short-lived transaction is the default transaction type. We will discuss the isolation level and the handling of transaction failure a bit later. The sidebars later in the chapter discuss the ACID properties and isolation level of transactions.

ACID Attributes of Transactions

ACID stands for Atomic, Consistent, Isolated, and Durable. These are the desirable properties that make a transaction a useful abstraction.

A transaction is said to be Atomic because either all the work in a transaction is done or none of it is done. The transaction executes exactly once or not at all.

A transaction preserves the Consistency of data. A transaction should not break application data integrity constraints—for example, when transferring money between accounts, the amount withdrawn must not be more than the amount deposited. Integrity constraints are dictated by application domain.

A transaction is a unit of Isolation. The system should behave as if each transaction is the only transaction running on it at a time, even though in reality hundreds of transactions may be in progress at any given time. Also see the sidebar “Transaction Isolation.”

A transaction is Durable. If a transaction completes, its effects cannot be lost despite system crashes. Conversely, if a transaction aborts, it can never be reattempted upon system recovery—whatever the final state, it is retained forever.


Transaction Isolation

Transaction isolation is a measure of what external data changes the transaction can “see.” Database textbooks refer to three kinds of phenomena that can occur if a transaction is not isolated. These phenomena are dirty reads, nonrepeatable reads, and phantoms.

A dirty read occurs when a transaction reads data that has not been committed. In this case, the transaction is exposed to partial work of another transaction in progress, which may abort or further change the data during its lifetime.

A nonrepeatable read occurs when upon re-reading the same data (rows) the transaction sees different values. This happens when other transactions have committed and modified values for existing data (rows) already accessed by the current transaction.

A phantom occurs when the transaction sees a different set of data (rows) for the same search criteria used to access the current data. This happens when other transactions have added to the resultset (new rows) while the current transaction is in progress.

An application may have a different level of tolerance for such phenomena. The desirable isolation level is therefore dependent on the application. Four isolation levels are defined based on these phenomena.

At the read-uncommitted isolation level, all three phenomena are possible. No locks are used to coordinate data access.

At the read-committed isolation level, dirty reads are prevented, but two other phenomena can occur. For this isolation level, transactions must wait for all “write” locks to be released and use a “read” lock to access the data.

At the repeatable read isolation level, only phantoms can occur. This is like the read-committed isolation level, with the added requirement that “read” locks be held for the lifetime of the transaction.

Finally, at the serializable isolation level, none of these phenomena occur; the transaction is isolated. This is accomplished through higher level table or index locks.

Long-lived transactions shed all pretence of specifying any isolation because of the high cost of retaining long duration locks. Short-lived transactions need to lock resources for a short time, and hence the locking overhead is acceptable. For short-lived transactions, one selects the level of isolation that the application can tolerate. Lesser isolation leads to more concurrency and throughput performance.


Long-Running Transactions

Long-lived (or long-running) transactions sacrifice isolation for concurrency and scalability. By sacrificing isolation, the data as seen by actions within the long-running transaction may change as the transaction progresses because of other external actions. In return, the long-running transactions are unlikely to block (or deadlock) because they do not keep resources (like databases) locked for the duration of the transaction. This results in the higher concurrency.

For DTC style transactions, using locking and the two-phase commit protocol, you can implement application transactions to have the desirable ACID properties. Long-lived transactions do not have recourse to these mechanisms. Granted that long-lived transactions sacrifice isolation, how can they be implemented to exhibit the other attributes in ACID? There are no easy answers!

Let's take a step back to gain some perspective. When you define any transaction, you are effectively declaring that a set of application-specific actions be performed in a manner that complies with the ACID properties of transactions. For long-lived transactions, you are making a similar declaration (okay, pronouncing ACID without the “I” is not easy!). You are stating that all actions enclosed by the transaction shape should run as a unit; however, you are accepting the fact that the enclosed actions could be exposed to unqualified data from other transactions.

For long-lived transactions, therefore, the onus is on you to understand your application domain and then structure the process flow, actions, and transaction boundaries such that the data seen by actions is always appropriate in the context of your application.

To help you to accomplish this, two features are provided by BizTalk Orchestration. One is the capability to nest transactions within a long-lived transaction, and the other is the capability to define exception processing for transactions. Each is discussed in turn in the following sections.

Nested Transactions

You can define a long-lived transaction to contain other transactions and flowchart shapes. By nesting transactions in this manner, you can build application logic by composing larger units of work using smaller units of work. The term unit of work is used to highlight the fact that your application defines what is a unit of work, taking into consideration the atomicity and data consistency requirements of your application. However, the term is really a synonym for transaction.

Nested transactions have the following characteristics. The body of a long-lived transaction can contain other transactions, whether long-lived or short-lived. Any deeper nesting is not supported. The body of short-lived transaction cannot contain any nested transactions. However, this is not really a limitation. Short-lived transactions are intended to be just that, short and quick, and therefore they can hold onto resource locks without introducing concurrency problems.

Figure 9.8 shows a process flow involving nested transactions taken from the samples shipped with BizTalk. You can find this sample schedule at Program FilesMicrosoft BizTalk ServerSDKXLANG SamplesNestedTxnsNestedTxns.skv, or a similar location depending on your installation. For clarity, the communication and implementation shapes have been hidden.

Figure 9.8. Nested transaction example.


Figure 9.8 shows an outer transaction, called Purchase. This is a long-running transaction. It is composed of many actions and a nested short-lived transaction called Payment. You can read up on the example in the SDK documentation, but the gist of the process flow is to order some merchandise, pay for it, and decide either to keep it or return it.

The three actions inside the Payment block are guarded by a DTC style transaction. The outer transaction, Purchase, may take a long time (days), and it has no such protection. However, it can treat Payment (the nested transaction) as if it were a single action. Note that the XLANG scheduler engine plays an important role in making sure that schedules themselves are durable and transaction aware. The engine is discussed in Chapter 11.

If a decision is made to return the merchandise, the process flow to the right ends in an Abort shape. Figure 9.9 shows the properties of the long-lived transaction and Figure 9.10 the properties of the short-lived transaction.

Figure 9.9. Properties of the long-lived transaction, Purchase.


Figure 9.10. Properties of the short-lived transaction, Payment.


Note that the long-running transaction has no timeout, and there is no option to specify isolation properties. Figure 9.10 shows the properties for the nested short-lived transaction.

You already saw a property page for a short-lived transaction, so most of this should be familiar. We have not yet discussed the two groups you see there: On Failure and Compensation. These have to do with exception processing, discussed next.

Transaction Exception Processing

Exception processing allows you to specify an alternative process flow to execute if a transaction fails. There are two scenarios to consider, and there are two corresponding mechanisms for processing exceptions.

The first scenario is that of a transaction failing. The failing transaction can be of any type, whether nested or not. When you click the button Add Code in the group On Failure, you instruct the BizTalk Orchestration designer to add a new page to the process flow drawing. This page is called On Failure of <Transaction>, where the token <Transaction> is replaced by the actual name of the transaction. The page presents a fresh surface to draw a new business process, complete with a Begin shape to start off the process.

The process you define on the On Failure of <Transaction> page is executed in lieu of the process enclosed by the <Transaction> shape. This is important. Remember, that the transaction shape draws a boundary around a process flow fragment, and it provides virtual Begin and End points for the process flow it encloses. The process flow you define on the On Failure of <Transaction> page replaces the entire process flow inside the failed transaction, between its internal start and end points.

The goal of the failure handling process flow is not to reattempt the transaction—that is automatically done based on the configured retry count. You also do not need to attempt to undo the effects of the failed transaction—by definition there aren't any effects to undo; the transaction simply failed. Your goal here is to have your process flow recover from the failed transaction. Typically, you will attempt a process flow that is much more likely to succeed—for example, sending a notification message, logging the event, or making a manual intervention.

The second scenario for exception processing is that of an outer transaction failing, but the nested transaction succeeding. You cannot abort the nested transaction that committed! This is where the notion of compensation comes in. The Add Code button in the Compensation group is available only in the property pages for a nested transaction. When you click this button, you instruct the BizTalk Orchestration designer to add a new page to the process flow drawing. This page is called Compensation for <Transaction>, where the token <Transaction> is replaced by the name of the nested transaction that succeeded. On this page, you draw the process flow to compensate for the nested transaction that occurred and completed but now needs to be nullified. For example, on this page, you may define a process to reverse charges on an account, or authorize a service call.

If there were multiple nested transactions, you could define a compensatory process flow for each of them. When the outer transaction fails, each compensatory process flow for a successful nested transaction is executed. If the outer transaction has an On Failure of <Transaction> page defined, then all compensatory flows run before the process flow for the failed outer transaction. The order of execution of the compensatory flows is not specified.

Figure 9.11 shows the tabs for pages that would appear for the Payment and Purchase transactions showed earlier, assuming that a compensation process for Payment and failure handling process for Purchase are defined.

Figure 9.11. Page tabs for transaction exception handling at the bottom.


For completeness, Figure 9.12 shows the compensation process for the Payment transaction. It consists of a transaction to ReverseCharges. You can cogitate on whether the long-running Purchase transaction, as implemented, merits being called a transaction given the application it is written for. The point is that although long-running transactions do not support DTC style rigorous semantics, they are still useful.

Figure 9.12. Compensation for Payment.


You may have noticed the Enabled check box on the property page of a transaction. If you don't check this box, the process flow on the corresponding page is not enabled. This is useful when developing the compensation code. The actual process flow page is retained; it is removed only if you click the relabeled button Delete Code.

We discussed exception handling for transactions, but when does a transaction failure occur? Based on the material covered so far, a transaction fails when one of the following occurs:

  • A transaction does not complete within timeout period, if specified.

  • A transaction exhausts its allotted number of retries.

  • The process flow within the transaction encounters the Abort shape.

  • The DTC aborts a transaction.

Note

An outer transaction does not necessarily abort if a nested transaction aborts. Merely, the next action in the outer transaction is attempted. The outer transaction aborts if it encounters the Abort shape or runs out of its allotted time, if any.


We'll wrap up this section on transactions with a few additional comments. One of the issues covered in Chapter 10 is state management; however, it is important to draw attention to this in this section also. The following paragraphs address this further.

It is important to recover the state of the schedule prior to a failed transaction. It is also important that the state of a schedule be durable so that the effects of a committed transaction are not lost. The XLANG scheduler engine takes care of this.

For state, in the case of a While loop, BizTalk Orchestration allows you the option of retaining the state for each iteration of the body of a While loop. This is a property of the While shape. If you set the property to preserve state for a While loop, then the process flow on the On Failure of <Transaction> page or the Compensation for <Transaction> page is called for each successful execution of the While loop prior to the point of transaction failure. If you don't preserve the state, then these pages are invoked only once, for the last successful execution of the While loop prior to the point of failure.

The need to correctly manage schedule state and transaction context along with dehydration and rehydration of schedules results in behavior that you must understand when implementing schedules. There are subtle differences between a schedule and its rehydrated clone, but let's not get ahead of ourselves here; these issues are covered in subsequent chapters on BizTalk Orchestration.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset