Darren Duncan wrote:

I think that the question of what would be a reasonable minimum to do now depends on what SQLite's current behaviour is when an individual SQL statement fails that is part of a larger transaction.
Of course not. A reasonable minimum is to do nothing and leave SQLite as is. :-)

Remember that each SQL statement is conceptually an implicit child transaction of its own.

If a failing SQL statement causes the entire transaction to implicitly rollback, then what you describe about any rollback causing the whole thing to rollback would be consistent.

If a failing SQL statement just results in only that statement not leaving a trace and other uncommitted statements in a transaction are still applied subject to be committed, then an explicit rollback must not affect anything but the immediate child-most transaction, to be consistent.

An SQL statement is atomic. It either completes or does nothing. If it fails it returns an error to the application.

It is up to the application to decide if an error warrants rolling back a transaction. The database never does that on its own. The application must execute a ROLLBACK statement. If a transaction is rolled back, it is done in an atomic fashion. The database is left in the same state it was before the transaction started. If you don't do this you have eliminated the atomicity property of the transaction.

The A in ACID is for atomicity. In Transaction Processing: Concepts and Techniques, Jim Gary and Andreas Reuter describe the atomicity property of a transaction as:

Atomicity: The transaction consists of a collection of actions. The system provides the all-or-nothing illusion that either all these operations are performed or none of them are performed; the transaction either commits or aborts.

Regardless, I like to think of SQL statement failures like exceptions,
But they are not. If you want, you can throw an exception when an error is reported to your application. When you catch the exception you can commit or roll back the transaction as appropriate.
and each transaction level can optionally act like a try-catch-block; a failed statement throws an exception, and each transaction in turn is rolled back up to said try-catch block, and anything done prior to the block being entered is not rolled back automatically.

Now of course, users would then have to explicitly mark places, perhaps best as an extension to the "begin transaction" statement that indicates whether a failure within that transaction will auto-effect any of its parents; its like the "begin" doubles as a try-block. Or that may not be the best syntax, so alternatives could be tried.
This is what a SAVEPOINT is for SQL:1999, PostgreSQL, Oracle, and many other standard databases. Using them, you can roll back to a savepoint rather than to the beginning of the transaction by specifying the savepoint to return to in your rollback statement. This is the standard way to get the effect you are looking for with nested transactions that can be rolled back. In fact, savepoints can be implemented with nested transactions.


I will also say for the record that partial rollbacks are useful. Having all layers rolling back unconditionally is like having a web browser program that exits if it has trouble loading a web page, rather than just saying sorry and moving on. Sometimes it is reasonable to only rollback the "load this page" transaction rather than the "main()" transaction. Users may want to try again, or try going to a different page.

Reasoning by analogy is always dangerous, but committing changes to a database atomically is *nothing* like browsing the web.

If you have a real example of an database application that needs to commit a part of a transaction, I'm fairly sure the application can split that optional part into a separate transaction. I mean, if that action can fail and the rest of the transaction can still be said to be complete, then there is no need to perform that action at that time along with the other actions in the transaction. It can be done later, and either succeed or fail on its own, because obviously it didn't matter if it succeeded or failed in the first place.

Dennis Cote



-----------------------------------------------------------------------------
To unsubscribe, send email to [EMAIL PROTECTED]
-----------------------------------------------------------------------------

Reply via email to