Yesterday I demonstrated how a Transaction can be inherited by processes.  This means that a process never designed for Transactions can run in a Transacted mode.  Clearly, this has profound implications.  Some applications may exhibit odd or unexpected behavior if run in this way.  It isn't really possible to enumerate every possible case where odd things will happen; the best approach is to use caution.  Let's consider a few cases.

Suppose a non-transactionally aware application recorded a simple log file.  When run from within a transaction, those log records become isolated from other processes, and can be completely rolled back, possibly defeating the purpose of the log.  Applications that record log accesses should be aware of this possibility, and may choose to ensure that they switch out of a Transacted state before performing logging.

Isolating applications that use temporary files into Transactions has the side-effect that it becomes virtually impossible to recover data in event of failure.  Suppose you ran Microsoft Word in a transaction; Word will create a temporary file of your document, which is isolated from public view.  If Word were to fail, the temporary file remains inaccessible and Word can't be invoked to recover that lost data in event of a crash.  Depending on how Transactions are managed in this case, the Transaction may even be rolled back, purging the temporary file forever, and losing data in the process.

The most interesting case, in my opinion, involves launching an application with incomplete Transaction support from within a Transaction.  The test application in my previous post is a good example: what happens if test itself is run from within a Transaction? It will blindly create a second, completely independent transaction, do some work, and commit that Transaction.  Now the application which called the test application wants to rollback its Transaction - which it does, successfully - but all of the changes made by the test application remain committed to disk.

Inheritable Transactions are a powerful user tool, but are also another case that application developers should be aware of.  Well-behaved applications should firstly check if they are being executed within a Transaction and make appropriate ajustments.  What an application should do next depends in part upon what the application was intended to do in the first place.  Maybe the application should simply exit (with an appropriate error message, of course.)  Maybe the semantics of an application could be changed - instead of a Service Pack installer maintaining its own Transaction, it could instead rely on its inherited Transaction and not duplicate Transactional logic.  A well behaved application should never silently ignore the existence of an inherited Transaction; doing this only leads to confusing, potentially inconsistent results.

The test application does ensure that the child process has completed before commiting the Transaction.  This code is particularly important.  If the test application commits the Transaction while a child process is still using it, filesystem calls made by the child will begin to fail.  This includes both reads and writes: all filesystem calls made by the child are made in the context of an invalid Transaction.  The child may not be designed to handle this case elegantly.  When inheriting Transactions, an application should make sure that no process is still running within that Transaction before committing or rolling back.

So what happens if the process being executed is intending to remain executing permanently? Bluntly: don't do this.  That process will eventually exhaust all the resources for recording Transactional changes, and will invariably fail eventually, possibly failing other processes as well.  If a server is to run with Transaction support, it should be designed to support Transactions natively.

In each case of using Transactions, the first question to ask yourself is always: what does this mean? What should I expect?  The implications of Transactions may easily break existing applications, so use caution doing this.  However, Transactional inheritance when used correctly enables you to leverage this new technology without heavy reinvestment in new applications.