A for Atomicity,也就是原子性;
C for Consistency,也就是一致性;
I for Isolation,也就是隔离性;
D for Durability,也就是持久性。
分别是啥意思呢?
原子性就是说事务是一个最小单位,要么成功,要么失败,不存在中间状态;
一致性就是说事务符合某些约束,比如我给你转账,你的账户多了10块钱,我的账户就会少10块钱。
隔离性就是说在事务进行的过程中,两次状态转换互不影响,举个栗子就是说我和别人一起给转账,这两笔转账之间互不影响。
持久性是说事务再进行的过程中,状态一旦提交,不会因为其他原因而回退,状态结果将永久保留。
初次之外,在MySQL中,事务具有四种隔离级别,分别是Read Uncommitted,Reas Committed,Repeatable Read以及Serializable.为什么这么称呼,有什么区别,后续我们会讨论。
其实这些概念说起来比较抽象,大家也都理解。试想一下,如果有很多用户需要在同一时间内访问某一台服务器,这样的设计,如果不进行并发控制,会遇到什么问题。这里我们把会出现的各种问题都罗列一下。
01
脏读
我们举个例子来看这个问题,后续的问题中,我们也将采用这个例子:
mysql:yeyztest 20:47:09>>
create table hero(
id int primary key auto_increment,
name varchar(),
kongfu varchar()) engine=innodb default charset=utf8;
Query OK, rows affected (. sec)
mysql:yeyztest 20:48:03>>insert into hero values (,'郭靖','降龙十八掌'); Query OK, row affected (. sec)
mysql:yeyztest 20:48:42>>select * from hero;
+----+--------+-----------------+
| id | name | kongfu |
+----+--------+-----------------+
| 1 | 郭靖 | 降龙十八掌 |
+----+--------+-----------------+
row in set (. sec)
可以看到,我们首先创建一张hero表,其中id是自增列,插入一条数据,如上图。
然后我们把事务的隔离级别设置成最低的,也就是RC隔离级别,然后来看我们的实验:
事务开启之前,我们查询到表里面的name是"郭靖",而在事务执行的过程中,由于在session B上的操作,导致name里面的值变为了"yeyz",也就是我们读到了一条脏数据,而这条脏数据,在session B进行了rollback之后,其实是一条不存在的数据,这是我们不想看到的结果,读到一条不存在的结果的这种现象我们称之为"脏读"。
02
不可重复读
不可重复读,顾名思义,就是不能重复的去读这条数据,否则会出现不一致的情况,我们来看下面的这个例子。
上面的例子可以看出来,我们在session A的事务中一致重复的去读一条记录,然后再session B中不停的去改这条记录,然后session A中的结果每次都会不一样,也就是说,不能重复的去读这个值,我们把这种情况称之为"不可重复读"。
03
幻读
幻读的概念是如果一个事务根据某些条件查询出来一些记录,然后另外一个事务向表中插入了一些符合这些条件的记录,那么原先的事务再次查询这个条件的时候,就能读出来一些其他的额外的记录。这就意味着发生了"幻读",举例如下:
session A中使用select * from hero where id>0这个条件去搜索相关信息,第一次搜出来了1条信息,当session B中执行了一个插入之后,第二次搜出来了2条信息,就像产生了"幻觉"一样,我们称这种情况为"幻读"。
这里需要特别说明一下,幻读是指读到了前一次没有读到的记录,如果说前一次包含这个记录,而后一次没有读取到这个记录,这样的场景不属于幻读。
幻读一定是记录变多的过程。
例如下面的过程,就不能称之为幻读:
因为前后对比,是记录减少了,这种情况不能称之为幻读,而且也没有具体的定义。
04
简单总结
在数据库中,我们按照上面的问题的严重性排序一下就是:
脏读>不可重复读>幻读
下面我们看看各种情况和隔离级别之间的关系:
关于这个关系的解读,后续我们在写MVCC的时候会详细介绍,今天先到这里吧。