一、什么是事务?
事务是由一系列操作组成的执行单位,这些操作要么都做,要么都不做
特性:
- 原子性:事务不可分割
- 一致性:事务开始前,结束后,数据库的完整性约束没有被破坏。
- 隔离性:事务之间是相互隔离的,具体的隔离级别我们接下来讨论
- 持久性:事务对数据库作出的修改是持久的而不是临时的。
在MySQL中,事务是这样定义的:
set autocommit=0 #事务开始
语句1;
语句2;
...
commit | rollback #事务结束
二、事务的并发问题
-
脏读:现在有两个事务T1,T2.T1事务对数据进行了修改,但还没提交,T2此时读数据读到的是T1修改后的数据,而过了一会之后T1执行回滚,那么T1做出的修改时临时的,而T2却读到了这个“脏”数据。
-
不可重复读:指的是事务T中两次读取相同的数据但结果却不一样,引发的原因有很多种,脏读也是一种"不可重复度",它要求的隔离级别比脏读更高。
-
幻影读:前面两种问题是针对属性的值的,而幻影读是针对记录的个数的,比如事务T1在执行过程中上一次查询数据还只有3条,再次查询时就变成了5条。它要求的隔离级别是最高的。
综上,大家有没有发现事务的并发问题和java中的并发问题非常相似,我们在数据库中是采用设置隔离级别来解决并发题的,这也类似于java中的加锁。并且,隔离级别设置的越高,你的执行效率就会越低,所以MySQL中默认的隔离级别是repeatable read(可重复读)而不是serializable(解决幻影读)
三、事务的隔离级别
#1.查看当前隔离级别
select @@tx_isolation;
#2.设置隔离级别
set session transaction isolation level 隔离级别
接下来让我们来了解不同隔离级别他们的差别:
-
read uncommitted:隔离级别最低,会出现脏读、不可重复读和幻影读。
-
read committed:隔离级别高于前一个,解决了脏读问题,但还无法解决不可重复读以及幻影读。
- 例:有事务T1,T2。T2隔离级别为read committed,当T1对数据修改完还未提交的时候,此时T2读数据读的是修改之前的数据,这是不是就解决了脏读的问题呢?但是当T1修改完后提交了,那么T2再次读数据,读的就是T1修改完之后的数据了,跟之前读的不一样了,这就是不可重复读。
-
repeatable read:解决了不可重复读,同一事务对相同的数据读取结果会保持一致,但没解决幻影读问题。
-
serializable:隔离级别最高,解决所有并发问题,但是在一个事务修改数据的时候,另一个事务无法读取数据,只有等它提交后别的事务才能读取,这也就是它为什么效率最低的原因。