http://www.hollischuang.com/archives/943在这个基础上添加
在DBMS中,事务保证了一个操作序列可以全部都执行或者全部都不执行(原子性),从一个状态转变到另外一个状态(一致性)。由于事务满足久性。所以一旦事务被提交之后,数据就能够被持久化下来,又因为事务是满足隔离性的,所以,当多个事务同时处理同一个数据的时候,多个事务直接是互不影响的,所以,在多个事务并发操作的过程中,如果控制不好隔离级别,就有可能产生脏读、不可重复读或者幻读等读现象。
在数据库事务的ACID四个属性中,隔离性是一个最常放松的一个。可以在数据操作过程中利用数据库的锁机制或者多版本并发控制机制获取更高的隔离等级。但是,随着数据库隔离级别的提高,数据的并发能力也会有所下降。所以,如何在并发性和隔离性之间做一个很好的权衡就成了一个至关重要的问题。
在软件开发中,几乎每类这样的问题都会有多种最佳实践来供我们参考,很多DBMS定义了多个不同的“事务隔离等级”来控制锁的程度和并发能力。
ANSI/ISO SQL定义的标准隔离级别有四种,从高到底依次为:可序列化(Serializable)、可重复读(Repeatable reads)、提交读(Read committed)、未提交读(Read uncommitted)。
下面将依次介绍这四种事务隔离级别的概念、用法以及解决了哪些问题(读现象)
未提交读(Read uncommitted)
未提交读(READ UNCOMMITTED)是最低的隔离级别。通过名字我们就可以知道,在这种事务隔离级别下,一个事务可以读到另外一个事务未提交的数据。
未提交读的数据库锁情况(实现原理)
事务在读数据的时候并未对数据加锁。
事务1
mysql> SELECT @@session.tx_isolation; +------------------------+ | @@session.tx_isolation | +------------------------+ | READ-UNCOMMITTED | +------------------------+ 1 row in set (0.00 sec) mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from student; +----+-------+ | id | name | +----+-------+ | 0 | 0 | | 3 | cc | | 4 | dd | | 5 | cp1 | | 6 | 666 | | 7 | 7 | | 8 | 8 | | 9 | 9 | | 10 | 10 | | 11 | 11 | | 12 | 12 | | 13 | 13 | | 15 | 15 | | 20 | 20 | | 77 | dfads | +----+-------+ 15 rows in set (0.00 sec) mysql> update student set name="000" where id = 0; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> commit; Query OK, 0 rows affected (0.01 sec)
事务2
mysql> select @@session.tx_isolation; +------------------------+ | @@session.tx_isolation | +------------------------+ | READ-UNCOMMITTED | +------------------------+ 1 row in set (0.00 sec) mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from student; +----+-------+ | id | name | +----+-------+ | 0 | 0 | | 3 | cc | | 4 | dd | | 5 | cp1 | | 6 | 666 | | 7 | 7 | | 8 | 8 | | 9 | 9 | | 10 | 10 | | 11 | 11 | | 12 | 12 | | 13 | 13 | | 15 | 15 | | 20 | 20 | | 77 | dfads | +----+-------+ 15 rows in set (0.00 sec) mysql> select * from student; +----+-------+ | id | name | +----+-------+ | 0 | 000 | | 3 | cc | | 4 | dd | | 5 | cp1 | | 6 | 666 | | 7 | 7 | | 8 | 8 | | 9 | 9 | | 10 | 10 | | 11 | 11 | | 12 | 12 | | 13 | 13 | | 15 | 15 | | 20 | 20 | | 77 | dfads | +----+-------+ 15 rows in set (0.00 sec) mysql> update student set name=0 where id = 0; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> update student set name=0 where id = 0; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from student; +----+-------+ | id | name | +----+-------+ | 0 | 0 | | 3 | cc | | 4 | dd | | 5 | cp1 | | 6 | 666 | | 7 | 7 | | 8 | 8 | | 9 | 9 | | 10 | 10 | | 11 | 11 | | 12 | 12 | | 13 | 13 | | 15 | 15 | | 20 | 20 | | 77 | dfads | +----+-------+ 15 rows in set (0.00 sec)
事务1 事务2