Mysql – Transaction basics. What is the result of 2 transactions running concurrently

concurrencyinnodbMySQLtransaction

I have a rather basic question on transactions.
Assume a table Account with a column amount. Now we have the following code:

BEGIN  
$amount = SELECT amount FROM ACCOUNT WHERE id = 123;  
$amount = $amount - 100;  
UPDATE ACCOUNT SET amount = $amount WHERE id = 123;    
COMMIT

Now if this snippet runs concurrently by 2 transactions, T1 and T2 what will happen?
I know that in MySQL by default the isolation level is REPEATABLE READ.
So let's say that amount initially is 500.
So when the 2 transactions finish will the final amount be 300 or 100?
I mean when they start both read from table which I guess is a shared lock.
When one updates the table it gets an exclusive lock right? So what happens to the other transaction? Will it proceed with the amount it "view" when it started i.e. 500?

Best Answer

There is no implicit shared lock in REPEATABLE READ isolation level.

You need to change the transaction sequence as follows:

ISOLATION LEVEL

You could switch to the SERIALIZABLE isolation level and disable autocommit. That way, the row is locked in shared mode implicitly.

If you want to stay with REPEATABLE READ or READ COMMITTED, you will have to call SELECT ... FOR UPDATE manually before doing the UPDATE.

QUERY (Optional Suggestion)

You should also experiment with

UPDATE ACCOUNT SET amount = amount - 100 WHERE id = 123; 

along with disabled autocommit and SERIALIZABLE isolation level.

I suggested this because you are doing two queries (SELECT and UPDATE) to change the amount. You could just do it with one query.

Your Question

Since locking reads and not implicit with REPEATABLE READ, there is a possibility of 500 being used twice.

You asked

Is it possible to set the isolation level at a connection level?I.e. not touch the global isolation level?

Yes, you can set the isolation level within the session:

SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL   {
    REPEATABLE READ
  | READ COMMITTED
  | READ UNCOMMITTED
  | SERIALIZABLE    }