Introduction to concurrency control and transaction management

by K. Yue

1. Concepts of Concurrency Control

Example:

Transfer $200 from account 1234 to 2345:

http://en.wikipedia.org/wiki/SQL#Transaction_controls

Task t1:
-- Assume: account 1234 = $1,000, account 2345: $500
UPDATE Account SET amount=amount-200 WHERE account_number=1234; -- (1) inconsistent state.
UPDATE Account SET amount=amount+200 WHERE account_number=2345; -- (2)

Sequence #1:

(1) Task t1 step (1)
(2) Task t1 step (2)

Sequence #2: read-write anomaly

(1) Task t1 step (1)
(2) Task t2 account reports: account 1234: $800, account 2345: $500 (Problem: access data from an inconsistent state)
(3) Task t1 step (2)

Sequence #3: crash and recovery.

(1) Task t1 step (1)
(2) System crashes; task t1 aborted after step (1) (Problem: system ending up in an inconsistent state)

Sequence #4: write-write anomaly

(1) Task t1 step (1)
(2) Task t2 read account amounts, calculate bonus and update accounts. Bonus will be calculated based on account 1234 = $800, account 2345: $500 (Problem: data update in an inconsistent state)
(3) Task t1 step (2)

Example: from Wikipedia

http://en.wikipedia.org/wiki/SQL#Transaction_controls

START TRANSACTION;
  UPDATE Account SET amount=amount-200 WHERE account_number=1234;
  UPDATE Account SET amount=amount+200 WHERE account_number=2345;

IF ERRORS=0 COMMIT;
IF ERRORS<>0 ROLLBACK;

 

Application Programmer' responsibility in terms of ACID:

  1. Atomicity: the transaction is either fully committed, or fully rollback. The programmer needs to define the scope and action of the transaction.
  2. Consistency: the execution of transaction should keep data consistent. It is the programmer's responsibility to ensure the logic for consistency. The following transaction can be atomic but inconsistent.

START TRANSACTION;
  UPDATE Account SET amount=amount-200 WHERE account_number=1234;
  UPDATE Account SET amount=amount+400 WHERE account_number=2345;

IF ERRORS=0 COMMIT;
IF ERRORS<>0 ROLLBACK;

2. MySQL Transaction Management

Example: using Sakila

If a customer rents a film (of inventory id 10, say), Sakila needs to perform the following in an atomic transaction:

  1. Insert a new row into the rental table with inventory_id 10.
  2. Insert a new row into the payment table with the rental_id automatically created in (1).

This can be accomplished by the following code:

drop procedure rent_film;

DELIMITER $$
#   A customer rents a video
create procedure rent_film(
   IN customer_id INT,       # cutomer who rents the video
   IN inventory_id INT,       # inventory video rented
   IN staff_id INT,          # staff id
   IN rental_fees DECIMAL(5,2)) # FEES PAID TO RENT THE VIDEO INITIALLY
LANGUAGE SQL
NOT DETERMINISTIC
READS SQL DATA
SQL SECURITY DEFINER

BEGIN

DECLARE rental_id INT;

START TRANSACTION;
INSERT INTO rental(rental_date, inventory_id, customer_id, return_date, staff_id)
VALUES (CURRENT_TIMESTAMP(), inventory_id, customer_id, NULL, staff_id);

SET rental_id := LAST_INSERT_ID();

INSERT INTO payment(customer_id, staff_id, rental_id, amount, payment_date)
VALUES(customer_id, staff_id, rental_id, rental_fees, CURRENT_TIMESTAMP());

IF (@@error_count =0) THEN
   COMMIT;
ELSE
   ROLLBACK;
END IF;

END $$

DELIMITER ;

Testing:

CALL rent_film(1,10,1,1.99);

select * from rental
order by rental_id desc
limit 1;

select * from payment
order by payment_id desc
limit 1;

 

Note: