MySQL autocommit探究
-- sessionA:tx_isolation=REPEATABLE-READ mysql> select connection_id(); +-----------------+ | connection_id() | +-----------------+ | 28 | +-----------------+ 1 row in set (0.00 sec) mysql> show variables like '%autocomm%'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | OFF | +---------------+-------+ 1 row in set, 1 warning (0.00 sec) mysql> select * from a; +----+ | id | +----+ | 1 | +----+ 1 row in set (0.00 sec) mysql> select * from a; Empty set (0.00 sec) -- sessionB:tx_isolation=REPEATABLE-READ(注意这里已经是另一个session了!sessionB!) mysql> select connection_id(); +-----------------+ | connection_id() | +-----------------+ | 29 | +-----------------+ 1 row in set (0.00 sec) mysql> show variables like '%autocomm%'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | OFF | +---------------+-------+ 1 row in set, 1 warning (0.00 sec) mysql> select * from a; +----+ | id | +----+ | 1 | +----+ 1 row in set (0.00 sec)
sessionA把数据删掉之后,sessionA就算此时没有commit,在sessionA中再次查询,也是查询不到数据的。(废话,因为已经删掉了嘛!)
那么问题1来了,此时在sessionB中是否能查询出id=1的这条数据呢?
ok,如果在sessionA执行一下commit;
-- sessionA mysql> select connection_id(); +-----------------+ | connection_id() | +-----------------+ | 28 | +-----------------+ 1 row in set (0.00 sec) mysql> commit; Query OK, 0 rows affected (0.01 sec)
那此时问题2来了,sessionB执行select * from a;是否能查询到id=1的数据呢?
答案:
问题1:可以查到id=1的数据。
因为当前tx_isolation=REPEATALBE-READ,所以在sessionA中未提交的事务,在其他事务中,是看不到的。(而如果tx_isolation=READ UNCOMMIT,则可以看到未提交事务的修改。)
问题2:也可以查到id=1的数据。下面是证据:
-- sessionB mysql> select connection_id(); +-----------------+ | connection_id() | +-----------------+ | 29 | +-----------------+ 1 row in set (0.00 sec) mysql> select * from a; +----+ | id | +----+ | 1 | +----+ 1 row in set (0.00 sec)
原因下面说,先来说一下此时如何在sessionB中看到的数据和sessionA一致呢?只需要在sessionB中commit;一下就ok了。
-- sessionB mysql> commit; Query OK, 0 rows affected (0.00 sec) mysql> select * from a; Empty set (0.00 sec)
ok,这里说一下个人理解(如有错误,请留言提出):
由于autocommit=0,此时事务并不会自动提交,可以理解为在开启sessionB的时候,就默认开启了一个事务(start transaction;)。
而在sessionB中执行commit,可以理解为commit是为了让sessionB的事务结束,因为在tx_isolation=REPEATABLE-READ的隔离级别下,在一个不提交或者不rollback的事务中,无法看到其他事务就算是commit的修改。这也是满足了ACID中的I,即隔离性。