前面我们说过,要获得最高的事务隔离性,可以采取序列化/串行的方式,代价是严重影响系统处理事务的吞吐量。就好像数据库是个多核CPU,事务串行后,那么意味着我们总是在使用单核,没办法发挥多核CPU的并行威力。


基于以上这个问题,大多数的数据库实现都为使用者提供了多个事务隔离级别;

Mysql提供的事务隔离级别有: Read Uncommitted,Read Committed,Repeatable Read,Serializable,级别依次递增。

Mysql默认的事务隔离级别是Repeatable Read


现在学习Read Uncommitted这种数据库隔离级别:

Read Uncommitted顾名思义,就是读未提交,也就是说事务所作的修改在未提交前,其他并发事务是可以读到的。下面我们来演示一下这个过程:

1. 假设现在有个学生小明连接到数据库去读取自己本学期的成绩,它设置session(当前连接)的事务隔离级别为Read Uncommitted:

xiaoming> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)

xiaoming> set session transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.00 sec)

xiaoming> select @@tx_isolation;
+------------------+
| @@tx_isolation   |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set (0.00 sec)

2. 就在这个时候,小明的班主任王老师也连接了数据库去登记学生本学期的成绩:

mr.wang> begin;
Query OK, 0 rows affected (0.00 sec)

mr.wang> insert into scores(name,score) values ("xiaoming", 59);
Query OK, 1 row affected (0.00 sec)

3. 当王老师还没有提交事务时,小明刚好开始查询自己的成绩,结果他查到自己考了59分,他伤心的要死:

xiaoming> begin;
Query OK, 0 rows affected (0.00 sec)

xiaoming> select * from scores where name = 'xiaoming';
+----+----------+-------+
| id | name     | score |
+----+----------+-------+
|  1 | xiaoming |    59 |
+----+----------+-------+
1 row in set (0.00 sec)

4. 小明查成绩之后,王老师发现自己登错了成绩,其实小明考了69分,于是他回滚了当前事务, 并重新录入了小明的正确成绩:

mr.wang> rollback;
Query OK, 0 rows affected (0.00 sec)

mr.wang> begin;
Query OK, 0 rows affected (0.00 sec)

mr.wang> insert into scores(name,score) values ("xiaoming", 69);
Query OK, 1 row affected (0.00 sec)

mr.wang> commit;
Query OK, 0 rows affected (0.00 sec)
5. 小明也没有复查成绩,因此整个寒假都过的很不开心,毕竟自己没有"及格"!


通过上述场景,我们发现,Read Uncommitted这个最低的事务隔离级别存在以下这些问题:

a. 允许脏读(dirty reads),就像上面王老师录入的错误成绩(脏数据)被小明读到一样

Logo

更多推荐