7
votes

I am currently trying to understand transaction isolation in MySQL, reading the book High Performance MySQL, 2nd Edition.

And here are their explanation of these two transaction isolation level.

READ COMMITTED

The default isolation level for most database systems (but not MySQL!) is READ COMMITTED . It satisfies the simple definition of isolation used earlier: a transaction will see only those changes made by transactions that were already committed when it began, and its changes won’t be visible to others until it has committed. This level still allows what’s known as a nonrepeatable read. This means you can run the same statement twice and see different data.

REPEATABLE READ

REPEATABLE READ solves the problems that READ UNCOMMITTED allows. It guarantees that any rows a transaction reads will “look the same” in subsequent reads within the same transaction, but in theory it still allows another tricky problem: phantom reads. Simply put, a phantom read can happen when you select some range of rows, another transaction inserts a new row into the range, and then you select the same range again; you will then see the new “phantom” row. InnoDB and Falcon solve the phantom read problem with multiversion concur- rency control, which we explain later in this chapter. REPEATABLE READ is MySQL’s default transaction isolation level. The InnoDB and Falcon storage engines respect this setting, which you’ll learn how to change in Chapter 6. Some other storage engines do too, but the choice is up to the engine.

Questions:

1- In READ COMMITTED if this isolation level means that transaction can only see changes that were committed by other transactions, how come during the same transaction if you run same statement you can see different results ? Does that mean the following ?

    START TRANSACTION;
                SELECT balance FROM checking WHERE customer_id = 10233276;
                UPDATE checking SET balance = balance - 200.00 WHERE customer_id = 10233276;
            # >>> NEXT I MUST SEE THE NEW BALANCE, OR I AM WRONG ? 
            SELECT balance FROM checking WHERE customer_id = 10233276;
COMMIT;

2- In REPEATABLE READ if this isolation level allows phantom read, how come it guarantees that any rows a transaction reads will "look the same" in subsequent reads ? Doesn't the phantom reads refutes the guarantee this level has ?

3

3 Answers

8
votes

http://ronaldbradford.com/blog/understanding-mysql-innodb-transaction-isolation-2009-09-24/

REPEATABLE-READ

session 1 :

    MariaDB [test]> DROP TABLE IF EXISTS transaction_test;
    Query OK, 0 rows affected (0.22 sec)

    MariaDB [test]> CREATE TABLE transaction_test(
        ->   id   INT UNSIGNED NOT NULL AUTO_INCREMENT,
        ->   val  VARCHAR(20) NOT NULL,
        ->   created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
        -> PRIMARY KEY(id)
        -> ) ENGINE=InnoDB DEFAULT CHARSET latin1;
    Query OK, 0 rows affected (0.29 sec)

    MariaDB [test]>
    MariaDB [test]> INSERT INTO transaction_test(val) VALUES ('a'),('b'),('c');
    Query OK, 3 rows affected (0.08 sec)
    Records: 3  Duplicates: 0  Warnings: 0

    MariaDB [test]> START TRANSACTION;
    Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> SELECT * FROM transaction_test;
+----+-----+---------------------+
| id | val | created             |
+----+-----+---------------------+
|  1 | a   | 2016-04-01 10:09:33 |
|  2 | b   | 2016-04-01 10:09:33 |
|  3 | c   | 2016-04-01 10:09:33 |
+----+-----+---------------------+
3 rows in set (0.00 sec)

MariaDB [test]> select sleep(50);

then user2 run next code :

 MariaDB [test]> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

MariaDB [test]> INSERT INTO transaction_test(val) VALUES ('x'),('y'),('z');

commit;

then user 1

MariaDB [test]> SELECT * FROM transaction_test;
+----+-----+---------------------+
| id | val | created             |
+----+-----+---------------------+
|  1 | a   | 2016-04-01 10:09:33 |
|  2 | b   | 2016-04-01 10:09:33 |
|  3 | c   | 2016-04-01 10:09:33 |
+----+-----+---------------------+
3 rows in set (0.00 sec)

MariaDB [test]>

READ-COMMITTED

user1

SET SESSION tx_isolation='READ-COMMITTED';
TRUNCATE TABLE transaction_test;
INSERT INTO transaction_test(val) VALUES ('a'),('b'),('c');
MariaDB [test]> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

MariaDB [test]> select sleep(60);

then user2 run next code :

MariaDB [test]> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

MariaDB [test]> INSERT INTO transaction_test(val) VALUES ('x'),('y'),('zwfwfw');

Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

MariaDB [test]> commit;

then user1 finish query :

MariaDB [test]> SELECT * FROM transaction_test;
+----+--------+---------------------+
| id | val    | created             |
+----+--------+---------------------+
|  1 | a      | 2016-04-01 10:28:08 |
|  2 | b      | 2016-04-01 10:28:08 |
|  3 | c      | 2016-04-01 10:28:08 |
|  4 | x      | 2016-04-01 10:29:00 |
|  5 | 
y      | 2016-04-01 10:29:00 |
|  6 | zwfwfw | 2016-04-01 10:29:00 |
+----+--------+---------------------+
6 rows in set (0.00 sec)
2
votes

As per my understanding suppose balance was 1000 before starting this transaction.

After starting transaction and updating it to "balance = balance - 200", if you run again select statement within transaction then results will be as per below-

  1. If isolation level is READ COMMITTED then you will see result as 800.

  2. If isolation level is REPEATABLE READ then you will see result as 1000.

2
votes

In READ COMMITED, you see the information that had been committed, regardless if you are in a transaction or not, thus it´s not guaranteed integration in the information because it can changed multiple times. Instead of this is REPEATABLE READ that forbids you in a ocurrence of a transaction the modification(UPDATE) of information(integrity), but you can add information(INSERT ...)