Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!seismo!columbia!rutgers!sri-spam!mordor!lll-lcc!ptsfa!rtech!jeff From: jeff@rtech.UUCP (Jeff Lichtman) Newsgroups: comp.databases Subject: Re: BIG, BIG fun w/Informix cursors Message-ID: <1076@rtech.UUCP> Date: Tue, 21-Jul-87 01:56:35 EDT Article-I.D.: rtech.1076 Posted: Tue Jul 21 01:56:35 1987 Date-Received: Wed, 22-Jul-87 06:27:29 EDT References: <229@paisano.UUCP> Organization: Relational Technology Inc. Alameda, CA 94501 Lines: 98 From article <229@paisano.UUCP>, by demasi@paisano.UUCP (Michael C. De Masi): > To insure data integrity, I had put all update statements within the > context of a 'begin work ... commit work else rollback work' structure. > > IMPORTANT: Both 'commit work' and 'rollback work' have the side effect > of closing every active cursor in the whole damn program! > > (FLAME ON!!!) > Now this is not limited to cursors acted upon within the structure, or > indeed to cursors declared for update, but all of them. The nice person > I spoke to at Informix assured me that this was indeed a documented > feature of both 'commit work' and 'rollback work'. Documented or not, > I find this a rather bizarre concept. I thought the purpose of this > structure was to insure transaction integrity, not to do cleanup work > of record locks, etc. In my humble opinion, this is the kind of thing > best left to the programmer or to the database administrator itself and > should not be hidden within the context of a seemingly non-related > functionality. > (FLAME OFF!!!) Lord, do I feel better. > -- > Michael C. De Masi - AT&T Communications (For whom I work and not speak) Closing all cursors when committing or rolling back a transaction makes sense, and conforms to the ANSI SQL standard. It is easier to explain why "rollback work" should close all open cursors, so let me start with that. The "rollback work" statement is supposed to reset the database to the state it was in before the transaction began. It would be nearly impossible, in the general case, to position cursors properly after a "rollback work"; for example, suppose you had deleted a bunch of rows from a table, positioned a cursor just before these deleted rows, and then did a "rollback work". The deleted rows have to come back, so should the next row you fetch be the first deleted row or the one after the deleted row? Now, about releasing locks when committing or rolling back a transaction: The purpose of a transaction is to provide atomicity. That is, transactions assure that you don't see anyone else's updates before they're complete, and that no one sees your updates before they're complete. Transactions are also the basic unit of recovery (in case of a system crash, for example, all incomplete transactions will be backed out during recovery). Locking is only a technique for providing atomicity. Database systems release locks at commit or rollback time because they are no longer needed: the transaction has either been entirely committed or entirely backed out, so the locks can be released safely without jeopardizing consistency. To hold the locks longer than this wouldn't hurt consistency, but it would kill concurrency. It would be possible to build a system that would allow the programmer to control when the locks were released, but that would be putting the burden of maintaining database consistency on the programmer; that's a service that the DBMS should provide, and is one of the things that distinguishes a DBMS from a file system. Now that we've established why the DBMS releases locks at commit or rollback time, let's consider why cursors must be closed at commit time. Suppose you are in the middle of a transaction, and you have a cursor positioned in the middle of a table. Now you do a "commit work". Suppose we want the cursor to remain open; the DBMS would still have to release its locks, which would mean that the cursor couldn't maintain whatever locks it had on its current position. Suppose, before you tried to fetch the next row from the cursor, that someone destroyed the underlying table, or deleted the row that the cursor was going to advance to, or added a row in front of the one it was to advance to. What should happen? Not only would it be extremely difficult to implement the DBMS to account for all possible cases of trying to use a cursor that has had the locks swept out from under it, it would be difficult to define what should happen in all cases (and many definitions would necessarily be arbitrary). It seems that Mr. De Masi got into this mess by trying to use "commit work" and "rollback work" to guarantee the success or failure of individual database statements. That is not a correct use of transactions. It appears to me that Mr. De Masi is looking for statement atomicity; that is, he wants every individual database statement to completely succeed or be backed out. This is something that every relational DBMS should provide for the user. I'm not familiar enough with Informix to say whether it does this, but it's a pretty good bet that it does. Therefore, there should be no need to test every update and either commit it or roll it back; the DBMS will leave in the effects of every successful statement, and back out the effects of every statement that couldn't complete due to some DBMS error. In SQL, the effects of all successful statements in the current transaction are committed at the time of a "commit work" statement, or backed out at the time of a "rollback work" statement. It's possible that I misinterpreted Mr. De Masi's statements, and what he's really looking for is a general-purpose way of getting rid of unwanted updates (e.g. a program makes a successful update, then later on in the transaction it decides it shouldn't have made the update and needs to get rid of it). Standard SQL doesn't provide any tools for doing this, and I'm not aware of any DBMS that makes this easy for you. If your tables all have unique primary keys (always a good idea), you could write your program so that it remembers the old row and the new key; that way, you could put back the old row if you wanted. -- Jeff Lichtman at rtech (Relational Technology, Inc.) "Saints should always be judged guilty until they are proved innocent..." {amdahl, sun}!rtech!jeff {ucbvax, decvax}!mtxinu!rtech!jeff