UPDATE employee SET salary = salary + 1000 WHERE fname='John' and lname='Smith' |
is executed as follows:
|
|
The following 2 update operations are performed simultaneously :
UPDATE_1: UPDATE checkingAccount SET balance = balance - 100 WHERE account_no = 12345678 |
UPDATE_2: UPDATE checkingAccount SET balance = balance + 1000 WHERE account_no = 12345678 |
UPDATE_2: read balance
===> 4000
UPDATE_1: read balance
===> 4000
UPDATE_2: Compute balance + 1000
===> 5000
UPDATE_1: Compute balance - 100
===> 3900
UPDATE_2: Write balance
===> writes 5000
UPDATE_1: Write balance
===> writes 3900 (overwriting 5000 !!!)
|
Here is an example of a unsynchronized parallel execution of a multi-threaded program that exhibit this inconsistent behavior (taken from another course that I teach):
Compile with: g++ -pthread -o thread02 thread02.C
Run it with: a.out 10, do it several times... you will see different answers each time...
The reason is that the variable N is updated (read, changed and written back) by multiple threads of executions (users if you will).
Here, I just want to show you that updates made to the database are always tentative until the system can determine that the updates are "safe"
|
| This experiment shows you that the updates made are not propagated to the database until transaction commits |
| User 1 | User 2 |
|---|---|
SELECT ssn, fname, lname, salary
FROM employee
WHERE fname='John'
AND lname='Smith';
>> 123456789 John Smith 30000
|
Don't do anything... |
| Don't do anything... |
SET autocommit = 0;
START TRANSACTION;
UPDATE employee
SET salary=31000
WHERE fname='John'
AND lname='Smith';
>> 1 row updated
|
| Don't do anything... |
SELECT ssn, fname, lname, salary
FROM employee
WHERE fname='John'
AND lname='Smith';
>> 123456789 John Smith 31000
(Data in buffer has been updated !)
|
SELECT ssn, fname, lname, salary
FROM employee
WHERE fname='John'
AND lname='Smith';
>> 123456789 John Smith 30000
(Data in database has
NOT been update yet !)
|
Don't do anything... |
| Don't do anything... |
COMMIT; >> Query OK, 0 rows affected (0.03 sec) |
SELECT ssn, fname, lname, salary
FROM employee
WHERE fname='John'
AND lname='Smith';
>> 123456789 John Smith 31000
(FINALLY !!!)
|
Don't do anything... |
| This experiment shows you that the updates made may need to wait to see it they are safe |
| User 1 | User 2 |
|---|---|
SELECT ssn, fname, lname, salary
FROM employee
WHERE fname='John'
AND lname='Smith';
>> 123456789 John Smith 30000
|
Don't do anything... |
| Don't do anything... |
SET autocommit = 0;
START TRANSACTION;
UPDATE employee
SET salary=salary+1
WHERE fname='John'
AND lname='Smith';
>> 1 row updated
|
| Don't do anything... |
SELECT ssn, fname, lname, salary
FROM employee
WHERE fname='John'
AND lname='Smith';
>> 123456789 John Smith 30001
|
SET autocommit = 0;
START TRANSACTION;
UPDATE employee
SET salary=salary+2
WHERE fname='John'
AND lname='Smith';
>> updated HANGS !!!!!!!!!!
(It's waiting for
the other update to finish...)
Outcome 1: after waiting a long time:
ERROR 1205 (HY000):
Lock wait timeout exceeded;
try restarting transaction
|
Don't do anything... |
| Don't do anything... |
COMMIT; // If you do this quick enough
// the other update will finish !
>> releases Update 1 !!!
|
Outcome 2: Commit after a short wait:
SELECT ssn, fname, lname, salary
FROM employee
WHERE fname='John'
AND lname='Smith';
>> 123456789 John Smith 30003
>> commit;
|
Don't do anything... |
The lock time out is set to 50 sec by default....
Try: rollback !!!
Comment: use "cheung-sql" use companyDB SET autocommit = 0; /* Update now happens only on COMMENT */ |
|
|