Question

AFAIK running transactions as READ UNCOMMITTED means that there is no lock, so every change caused by a transaction is immediately visible to other transactions.

Is it correct to assume that this is the same behaviour we get with any transaction if we enable AUTOCOMMIT? AFAIK in this case, as well, the effects of any query are immediately visible to others.

Of course, the two concepts are somewhat different, semantically, but is there any difference in what's actually happening?

I'm interested in a general answer, though I do tend to care more about MySQL and Microsoft SQL Server.

Was it helpful?

Solution

This is an answer assuming MySQL/InnoDB. Visibility rules are slightly different on Oracle:

No, as you say, SET autocommit = 1 (default behavior) is that every single query is like if it has a START TRANSACTION; ... COMMIT; around it, committing after every query. That is different from READ UNCOMMITTED (which doesn't mean that there is not a lock). InnoDB will always lock the row affected during its operation, the difference is that as the transaction commits just after the statement is executed, the lock will be released just afterwards in all cases.

However, even if you are using autocommit=1, rollback area cannot be purged inmediately when using tx_isolation > READ COMMITED, because other long-running transactions may need those values.

To show you the difference, I can show you an example:

session1> create table test (id int primary key, c varchar(20)) ENGINE=InnoDB;
Query OK, 0 rows affected (0.15 sec)

session1> set autocommit = 1;
Query OK, 0 rows affected (0.00 sec)

session2> set autocommit = 1;
Query OK, 0 rows affected (0.00 sec)

session1> select * from test.test;
Empty set (0.04 sec)

session2> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

session2> insert into test values (1, 'a');
Query OK, 1 row affected (0.10 sec)

session1> select * from test.test;
Empty set (0.04 sec)

Even if the other session is is using autocommit = 1; session 1 can't see the changes of session 2 because a transaction is ongoing. Also:

session1> create table test (id int primary key, c varchar(20)) ENGINE=InnoDB;
Query OK, 0 rows affected (0.15 sec)

session1> set autocommit = 1;
Query OK, 0 rows affected (0.00 sec)

session2> set autocommit = 1;
Query OK, 0 rows affected (0.00 sec)

session1> select * from test.test;
Empty set (0.04 sec)

session1> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

session1> select * from test.test;
Empty set (0.04 sec)

session2> insert into test values (1, 'a');
Query OK, 1 row affected (0.10 sec)

session1> select * from test.test;
Empty set (0.04 sec)

Session 2 cannot see the new value autocommited in session 2 becase start transaction + select is like if you had executed start transaction with consistent snapshot, so in InnoDB's default level "REPEATABLE READ", it cannot be seen even if it has (auto) commited on the other session.

Of course, if you only use autocommit mode, and no longer transactions in any connection, READ COMMITED and READ UNCOMMITED are equivalent, but not because it changes its visibility, but because you commit every single query. Things also get more complex if you throw other non-transactional engines into the mix.

As a side effect, mysql 5.6 changes InnoDB autocommit SELECT into read-only transactions, boosting its performance a bit.

Licensed under: CC-BY-SA with attribution
Not affiliated with dba.stackexchange
scroll top