Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!mnetor!uunet!seismo!husc6!mit-eddie!ll-xn!ames!lll-lcc!lll-tis!ptsfa!rtech!jeff
From: jeff@rtech.UUCP (Jeff Lichtman)
Newsgroups: comp.databases
Subject: Re: BIG, BIG fun w/Informix cursors
Message-ID: <1091@rtech.UUCP>
Date: Sat, 25-Jul-87 03:45:55 EDT
Article-I.D.: rtech.1091
Posted: Sat Jul 25 03:45:55 1987
Date-Received: Sun, 26-Jul-87 00:36:26 EDT
References: <230@paisano.UUCP>
Organization: Relational Technology Inc. Alameda, CA 94501
Lines: 145

From article <230@paisano.UUCP>, by demasi@paisano.UUCP (Michael C. De Masi):
> In article <1076@rtech.UUCP>, jeff@rtech.UUCP (Jeff Lichtman) writes:
>> From article <229@paisano.UUCP>, by demasi@paisano.UUCP (Michael C. De Masi):
>> 
>> 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...
> 
> Now granted, I probably don't have the level of understanding about
> database theory that you do, but what about purely readonly queries that
> do not cause any locking?

Usually, a DBMS will get and hold shared locks (also called "read locks")
until end transaction time.  What most DBMS's guarantee by default is
serializability, also called "level-three consistency".  A set of
concurrent transactions is serializable if there is some way of
doing all of the transactions non-concurrently and getting the same
result.  That is, if you can untangle all of the interleaved operations
in your concurrent transactions, and then can find some way of laying
your transactions end-to-end in such a way that it would produce the
same result, the transactions are called serializable.

This can be a hard concept to absorb at first, so I'll put it a different
way: the job of concurrency control in a DBMS is to ensure that users get
a consistent view of the data.  For a read-only transaction, this requires
two things: that the transaction not be able to see other users' uncommitted
updates, and that reading the same record more than once within the same
transaction will yield the same values every time.  This requires getting
and holding read locks until end transaction time, even if it is a read-only
transaction.

Suppose, for instance, that you have database containing account information.
There are two programs running: one is using a read-only transaction to
add up all the accounts to make sure things balance.  Another is running
transactions to transfer funds between accounts.  If the read-only transaction
didn't get read locks, it would be possible for it to see some half-done
updates from the transfer transactions, and the accounts wouldn't balance.

(Note that there are other methods of concurrency control besides locking.
I won't discuss any of the other methods here.)

Now suppose that a similar situation exists, except the read-only
transaction has two parts: first, it tallies all accounts with a positive
balance, and then it tallies all accounts with a negative balance.  Again,
assume that there is another set of transactions going on at the same time
that transfer funds between accounts.  If the read-only transaction doesn't
hold its locks until end transaction time, it's possible that an update
to an account will cause it to be seen as a positive-balance account
on the first pass, and a negative-balance account on the second pass.

Thus, in order to guarantee the user a consistent view of the data,
a DBMS must get and hold locks, even in a read-only transaction.  This
is true in the general case.  However, if the DBMS knew enough about
the user's application, it might be able to figure out when locks were no
longer needed and release them earlier.  For example, a transaction that
does nothing but read from a single table, and never re-reads anything,
doesn't need to hold its read locks until the end of the transaction; it
only needs to hold its locks on each record, page, or whatever, until the
application is done with the it.  Please note, however, that a DBMS has no
way of knowing whether this will be true, because it doesn't have the brains
to study the application to see what it's doing.  The programmer does
have the brains, however.  Some DBMS's allow the user to control
locking in various ways; Ingres, for instance, allows the user to
tell it not to use locks when reading.  But all relational DBMS's that I
know of use level-three consistency as the default.  That is, some DBMS's
allow the user to risk seeing inconsistent views of the data, but it
must be done by the explicit action of the user.

> Granted, commiting an update does change the
> nature of a given table, but can't that happen anyway?  That is, if I
> do a readonly query of a group of database records, and one gets changed
> by another process or user before I advance to that record, won't I get
> incorrect or no longer existing data, or is there some functionality
> that takes care of this of which I'm not aware?  If so, couldn't this
> same fuctioanlity be used to keep readonly cursors open under the
> circumstances I've described?

This could be a problem if read-only transactions didn't get and hold
locks.  But they do, and a consequence is that even read-only transactions
won't see another transaction's incomplete updates.  It is possible for
one transaction to see another's *comitted* updates, but that's perfectly
OK.

>> 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...
> 
> No, not unless you consider that one database 'transaction' from the
> viewpoint of the user, may actually consist of any number of individual
> database statements, any one of which is subject to failure...

It sounded to me like the application was written something like this:

	database statement;
	if (success)
		commit work;
	else
		rollback work;

	database statement;
	if (success)
		commit work;
	else
		rollback work;

	database statement;
	if (success)
		commit work;
	else
		rollback work;

	...

	commit work;

When it should be written like this:

	database statement;
	if (failure)
		rollback work;

	database statement;
	if (failure)
		rollback work;

	database statement;
	if (failure)
		rollback work;
	...

	commit work;

I have left out some control structures, but you get the idea.  "Success"
and "failure" here don't necessarily refer to the database statements;
they could be talking about other conditions that arise in the application.

> Michael C. De Masi - AT&T Communications (For whom I work and not speak)
> 3702 Pender Drive, Fairfax, Virginia 22030   Phone: 703-246-9555
> UUCP:   seismo!decuac!grebyn!paisano!demasi
>      "Life.  Don't tell me about life." - Marvin, the paranoid android
-- 
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