什么是事务
事务是一个原子操作单位,一个事务里面的操作要么全部成功,要么全部失败。
事务四大特性:ACID
-
原子性(Atomicity): 一个事务里的操作要么全部成功,要么全部失败
-
一致性(Consistency): 事务里有一个操作失败,事务修改过的数据全部要回滚到事务前的状态
-
隔离性(Isolation): 事务查看数据时数据所处状态,要么是在另一事务执行之前,要么就是另一事务执行之后,事务不会查看中间状态的数据。
-
持久性(Durability): 事务提交后,它对数据的修改是永久的。
事务并发会引起的三大问题
- 脏读:一个事务会读取到另一个事务未提交的数据。(读取到未提交数据)
例子:事务A修改了数据但还未提交,事务B读取到了事务A修改的数据。然后事务A因为某些错误回滚了,这个时候事务B读取到的数据就是脏的,这就是脏读。
- 不可重复读:在同一事务内,事务两次读取到的数据是不一样的。(同一条数据但不一致)
例子:事务A读取了一条数据之后,事务B修改了这条数据并提交了事务,然后事务A再次读取这条数据,就会发现两次结果不一致。这就是不可重复读。
- 幻读:事务中的同一个查询在不同的时间产生不同的行集,这个就是幻读问题。(数据条数不一样)
例子:事务A使用一定的条件查询,然后事务B增加了符合条件的记录,当事务A再次查询的时候,发现两次查询的结果集不一样,好像产生了幻觉。这就是幻读。
我在网上看幻读概念的时候,有人说:“如果事务A 按一定条件搜索, 期间事务B 删除了符合条件的某一条数据,导致事务A 再次读取时数据少了一条。这种情况归为 不可重复读”。附上链接:面试官一上来就问Mysql:幻读到底是什么?
然后,我就去MySQL官方文档看它对于幻读的定义。附上链接:Phantom Rows。
MySQL官方解释: The so-called phantom problem occurs within a transaction when the same query produces different sets of rows at different times.
翻译:当同一条查询在不同的时间产生不同的结果集,所谓的幻读问题就会在事务中发生。
其实看到这里,我们可能会有一些问题:那就是事务的隔离性不是保证了一个事务只能读取另一个事务执行前或执行后数据的状态吗?
为什么会出现上面的这三个问题?
为了回答这个问题,我们就要先看看事务的隔离级别
事务隔离级别
- 读未提交(Read uncommitted): 一个事务可以读取另一个未提交事务的数据。
在这种事务隔离级别下,会发生脏读、不可重复读、幻读的问题。
- 读已提交(Read committed): 一个事务只能读取已提交事务的数据。
在这种事务隔离级别下,可以解决脏读的问题,但仍然存在不可重复读和幻读的问题。
- 可重复读(Repeatable read): 当一个事务在读取数据的时候,另一事务不允许修改该数据。
在这种事务隔离级别下,可以解决脏读、不可重复读的问题,但仍会发生幻读的问题。
- 序列化(Serializable): 事务串行执行,效率最低。
在这种事务隔离级别下,可以解决脏读、不可重复读和幻读问题。
到这里,我们就知道为什么并发事务会出现上述的3种问题。这是因为事务并不是完全遵循事务的隔离性。
划分事务隔离级别的原因是为了能够根据不同的场景选择不同的隔离级别。隔离级别越高的事务,数据库的性能就会越低。