转载自:http://blog.csdn.net/taylor_tao/article/details/7063639


事务具有ACID四种特性。

但是Isolation并发可能引起如下问题:

1.脏读

允许读取到未提交的脏数据。

2.不可重复读

如果你在时间点T1读取了一些记录,在T2时再想重新读取一次同样的这些记录时,这些记录可能已经被改变、或者消失不见。

3.幻读

解决了不重复读,保证了同一个事务里,查询的结果都是事务开始时的状态(一致性)。但是,如果另一个事务同时提交了新数据,本事务再更新时,就会“惊奇的”发现了这些新数据,貌似之前读到的数据是“鬼影”一样的幻觉。


由ANSI/ISO定义的SQL-92标准定义的四种隔离级别

1.Read Uncommitted

2.Read Committed

3.Repeatable Read

4.Serializable


隔离解别脏读不可重复读幻读
Read UncommittedYYY
Read CommittedNYY
Repeatable(default)NNY
SerializableNNN

下面用Mysql数据库做一些小实验

Mysql 版本号


  1. mysql> select version();

  2. +------------+

  3. | version() |

  4. +------------+

  5. | 5.1.52-log |

  6. +------------+

  7. 1 row inset (0.00 sec)



查看InnoDB存储引擎 系统级的隔离级别 和 会话级的隔离级别

  1. mysql> select @@global.tx_isolation,@@tx_isolation;

  2. +-----------------------+-----------------+

  3. | @@global.tx_isolation | @@tx_isolation |

  4. +-----------------------+-----------------+

  5. | REPEATABLE-READ | REPEATABLE-READ |

  6. +-----------------------+-----------------+

  7. 1 row inset (0.00 sec)


更改会话级的隔离级别


  1. Session 1:

  2. mysql> set session tx_isolation='read-uncommitted';

  3. Query OK, 0 rows affected (0.00 sec)

  4. mysql> select @@global.tx_isolation,@@tx_isolation;

  5. +-----------------------+------------------+

  6. | @@global.tx_isolation | @@tx_isolation |

  7. +-----------------------+------------------+

  8. | REPEATABLE-READ | READ-UNCOMMITTED |

  9. +-----------------------+------------------+

  10. 1 row inset (0.00 sec)

  11. Session 2:

  12. mysql> select @@global.tx_isolation, @@tx_isolation;

  13. +-----------------------+-----------------+

  14. | @@global.tx_isolation | @@tx_isolation |

  15. +-----------------------+-----------------+

  16. | REPEATABLE-READ | REPEATABLE-READ |

  17. +-----------------------+-----------------+

  18. 1 row inset (0.00 sec)


更改系统级的隔离级别



  1. Session 1:

  2. mysql> setglobal tx_isolation='read-uncommitted';

  3. Query OK, 0 rows affected (0.00 sec)

  4. mysql> select @@global.tx_isolation,@@tx_isolation;

  5. +-----------------------+------------------+

  6. | @@global.tx_isolation | @@tx_isolation |

  7. +-----------------------+------------------+

  8. | READ-UNCOMMITTED | READ-UNCOMMITTED |

  9. +-----------------------+------------------+

  10. 1 row inset (0.00 sec)

  11. Session 2:

  12. mysql> select @@global.tx_isolation, @@tx_isolation;

  13. +-----------------------+-----------------+

  14. | @@global.tx_isolation | @@tx_isolation |

  15. +-----------------------+-----------------+

  16. | READ-UNCOMMITTED | REPEATABLE-READ |

  17. +-----------------------+-----------------+

  18. 1 row inset (0.00 sec)


关闭SQL语句的自动提交


  1. mysql> set autocommit=off;

  2. Query OK, 0 rows affected (0.00 sec)


查看SQL语句自动提交是否关闭


  1. mysql> show variables like 'autocommit';

  2. +---------------+-------+

  3. | Variable_name | Value |

  4. +---------------+-------+

  5. | autocommit | OFF |

  6. +---------------+-------+

  7. 1 row in set (0.00 sec)


建立实验表




  1. mysql> createtable tao (col1 tinyint unsigned, col2 varchar(20), primarykey(col1));

  2. Query OK, 0 rows affected (0.08 sec)

  3. mysql> show createtable tao \G;

  4. *************************** 1. row ***************************

  5. Table: tao

  6. CreateTable: CREATETABLE `tao` (

  7. `col1` tinyint(3) unsigned NOTNULLDEFAULT'0',

  8. `col2` varchar(20) DEFAULTNULL,

  9. PRIMARYKEY (`col1`)

  10. ) ENGINE=InnoDB DEFAULT CHARSET=utf8

  11. 1 row inset (0.00 sec)


演示脏读


0_1323675866uFk1.gif


更改隔离级别为Read Committed后,不存在脏读的问题。


  1. mysql> setglobal tx_isolation='read-committed';

  2. Query OK, 0 rows affected (0.00 sec)

  3. mysql> set session tx_isolation='read-committed';

  4. Query OK, 0 rows affected (0.00 sec)


演示不可重复读


0_132367931889fz.gif


更改隔离级别为Repeatable Read后,不存在不可重复读的问题。


  1. mysql> setglobal tx_isolation='repeatable-read';

  2. Query OK, 0 rows affected (0.00 sec)

  3. mysql> set session tx_isolation='repeatable-read';

  4. Query OK, 0 rows affected (0.00 sec)


幻读


0_1323680221HNhq.gif


更改隔离级别为完全串行化 Serializable 后,不存在幻读的问题。


  1. mysql> setglobal tx_isolation='serializable';

  2. Query OK, 0 rows affected (0.00 sec)

  3. mysql> set session tx_isolation='serializable';

  4. Query OK, 0 rows affected (0.00 sec)


在这种情况下,只允许一个事务在执行,其它事务必须等待这个事务执行完后才能执行。没有并发,只是单纯的串行。