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 */ |
|
|