CS 307, Lab #5

You are a Wizard, and will participate in magikal accounting.

You must be present in the lab to test transaction concurrency

In the jensen database on linux.ubishos.ca, the table gwb models a bank with accounts, specifically Gringott's Wizarding Bank. (See "Harry Potter and the Philosopher's stone," by J.K. Rowling.) You all have accounts with an initial balance of 1000 silver sickles.
[Wizards also use golden Galleons and copper Knuts, but as students at Hogwarts Academy you are too poor to have any Galleons, and Gringott's does not deal in Knuts.]
Banks neither create or destroy money, and practice "double entry" bookkeeping, so the total number of sickles should remain constant, if all goes well. The special account 'out' will represent all the sickles that are currently out of Gringott's vaults. Thus SUM(vault) must be kept constant, this is your collective responsibility as clients. Do not try to deceive Gringott's, it is run by goblins!
The model is, the 21000 sickles flow between accounts, also to and from 'out', represnting "outside the bank." Once 'out', you can spend your sickles or be robbed. This is no concern of the bankers, but you may use the column "pouch" to keep track of your coins.

All transactions should simply transfer money from one account to another. A Withdrawal of 20 will subtract 20 from your balance in your "vault", and add 20 to 'out'. A deposit will do the reverse. If an update would make a balance(vault) negative, it will be rejected, causing a transaction to abort, and have to be rolled back. Here is the table gwb, all "acct" codes are kept short to ease typing, they are in fact the first 3 letters of your linux acct.

Initially all the sickles are in vaults, so no deposits can reasonably be made. You will initially be able to withdraw money, always adding the same amount to 'out', and you may feel free to also add it to your "pouch" and you may also pick-pouch the sickles possessed by other wizards. Once some sickles are in circulation (in the 'out' "vault") you will be able to make deposits, but only up to the amount in your own "pouch."


 acct  | vault | pouch 
-------+-------+-------
 out   |     0 |     0
 jen   |  1000 |     0
 wbr   |  1000 |     0
 mcl   |  1000 |     0
 ada   |  1000 |     0
 ude   |  1000 |     0
 jdu   |  1000 |     0
 kgu   |  1000 |     0
 kgr   |  1000 |     0
 shu   |  1000 |     0
 ais   |  1000 |     0
 bjo   |  1000 |     0
 jla   |  1000 |     0
 jna   |  1000 |     0
 nng   |  1000 |     0
 wnu   |  1000 |     0
 sou   |  1000 |     0
 npo   |  1000 |     0
 mro   |  1000 |     0
 msy   |  1000 |     0
 dwi   |  1000 |     0
 aza   |  1000 |     0

     (22 rows)


In each part of the lab, you will try the following transactions
  1. Transfer some sickles from your account to the person on your right (Say, 20)
  2. Withdraw or deposit some sickles to your account. (Compensating entry to 'out' see above) This should cause even greater problems for 'out'
  3. Calculate the sum of "vault", is it still 0? SELECT SUM(vault)-21000 AS net FROM gwb;
Please talk a lot. This lab should be as noisy as a stock exchange, or the "Three Broomsticks" on Saturday night. There are check constraints, and a LOG of transactions.

2:30 First half-hour -- Get set, go wild (Schedule subject to change)

 Please sit around a table with others, and introduce yourself to your neighbors. Using the default "autocommit" (each SQL statement is a transaction by itself), first SELECT * FROM acct; and then figure out how to update the balances of yourself and your neighbor on your right, or the bank, and try the two required updates, for instance,:
    UPDATE gwb SET vault=880 WHERE acct='jen';
    UPDATE gwb SET vault= 120 WHERE
acct='out';   -- this one should abort
Discuss with everybody what is going on. Any money lost or gained? This schedule is subject to change depending upon what happens:

I will call a halt when there is enough confusion

Second "half hour": Read Committed transactions

Now I will attempt to bring the table to a consistent state (probably the initial one) and you will please be careful to use transactions. A transaction starts with begin, and ends with either commit or rollback (if you don't want to go through with it), try both. Like this:

BEGIN;
SELECT * FROM gwb;
UPDATE ... ;
SELECT SUM(vault)-21000 AS net FROM gwb; (this will be non-zero, but invisible to others!)
UPDATE ... ;
SELECT * FROM gwb; (optional)
SELECT SUM(vault)-21000 AS net FROM gwb; (this should again be zero)
ROLLBACK; ( or COMMIT; -- you decide)
It is possible that some UPDATE operations will hang. This means another transaction has updated the same row, but has not yet committed or rolled back. You will have to wait, during which time you may yell at your classmates to please make up there minds!
Important! Do wait, do NOT kill your terminal window, or the whole database may hang.
At some point you may get a message that your transaction has been rolled back due to deadlock. If this happens, DO announce the fact to everybody.

The bad news -- aborted transactions

If you make a syntax error during a transaction, you will have to type END; (or ROLLBACK;) and then start a new transaction. So be careful with your syntax!

Third "half-hour": A better way to do Banking transactions

Of course, figuring the new balance on paper is a bit of a problem. A better way is to let the server add or subtract, as mentioned in the users guide:

BEGIN;
UPDATE gwb SET vault = vault + 100 WHERE acct = 'jen';
UPDATE gwb SET vault = vault - 100 WHERE acct = 'out';
COMMIT;

"If two such transactions concurrently try to change the balance of account 'bank', we clearly want the second transaction to start from the updated version of the account's row. Because each query is affecting only a predetermined row, letting it see the updated version of the row does not create any troublesome inconsistency." (end quoting the users guide)

Try a transaction that will make some account negative. What happens? is any money lost (after it is rolled back?)

For all transactions such as these, which make linear changes, read committed should behave correctly. If not, we will try again with serializable.

Serializable transactions

Now we will try the same thing with serializable transactions. At some point I will start a non-linear transaction, adding interest to some accounts. This may delay you further. As long as everyone's transactions are properly done, there should be no inconsistencies. However, many transactions may have to be rolled back. To set this isolation level for all transactions, or for each individual transaction:

SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;

BEGIN;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- will only apply to this one
...

COMMIT;

Well, did anybody succeed? How many transactions aborted? Did you have to type "rollback;" to try again?
On the bright side, is the database in good order still?

More complex transactions?

Again according to the documentation, isolation level serializable is most commonly appropriate when a transaction will do multiple queries and requires an absolutely consistent view of the database. Using the initial "paper" method of figuring new balances may need this. The problem is that many transactions may get aborted.