面试需了解的事务及其特性
一、什么是事务?
事务:就是将一堆的SQL语句(通常是增删改操作)绑定在一起执行,要么都执行成功,要么都执行失败,即都执行成功才算成功,否则就会恢复到这堆SQL执行之前的状态
二、事务的四大特性(ACID)
1.原子性(Atomicity)
事务中所有操作是不可再分割的原子单位。事务中所有操作要么全部执行成功,要么全部执行失败。
2.一致性(Consistency)
事务执行后,数据库状态与其它业务规则保持一致。事务的成功与失败,最终数据库的数据都是符合实际生活的业务逻辑。如转账业务,无论事务执行成功与否,参与转账的两个账户金额之和在事务前后应该是保持不变的
3.隔离性(Isolation)
隔离性是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰。也就是说,在事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。
4.持久性(Durability)
一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制恢复数据。
三、事务并发读问题
什么是事务并发?
多个事务对相同的数据同时进行操作,这叫做事务并发。
在事务并发时,如果没有采取必要的隔离措施,可能会导致各种并发问题,破坏数据的完整性等。
1.脏读(dirty read)
在一个事务中,读取到另一个事务未提交更新的数据,即读取到了脏数据;
例如:在一个事务中,A给B转账100元但未提交事务,在另一事务中B查询账户金额,查询到了A未提交更新的数据,我们称之为脏读。
提示:需要将数据库的事务隔离级别设置为最低,才能够看到脏读现象
事务1:开启事务; A - 100 = 900; B + 100 = 1100; (没有提交事务)
事务2:开启事务; 查询B账户的金额 1100, 这个过程叫做脏读, 1100就是一个脏数据
2.不可重复读(unrepeatable read)
对同一记录的两次读取结果不一致,因为在两次查询期间,有另一事务对该记录做了修改(是针对修改操作)。
例如:在事务1中,前后两次查询A账户的金额,在两次查询之间,另一事物2对A账户的金额做了修改(并且也提交了事务),此种情况可能会导致事务1中,前后两次查询的结果不一致。这就是不可重复读。
事务1:开启事务—
第一次读取A账户的金额:1000
第二次读取A账户的金额:900
事务2:开启事务—
A账户 - 100 = 900;
提交事务—
3.幻读(虚读)(phantom read)
对同一张表的两次查询结果不一致,因为在两次查询期间,有另一事务进行了插入或者是删除操作(是针对插入或删除操作);
事务1:开启事务—
select * from acc where id=3;//不存在id为3的记录
insert into acc value(3,‘C’,2000); //操作失败
select * from acc where id=3;//存在id为3的记录
事务2:开启事务—
insert into acc value(3,‘C’,2000);
提交事务—
注意:mysql默认的是不允许出现脏读和不可重复读
四、事务隔离级别
1.READ UNCOMMITTED(读未提交数据)
安全性最差,可能出现任何事务并发问题(比如脏读、不可以重复读、幻读等);
2.READ COMMITTED(读已提交数据)(Oracle默认)
安全性较差,性能较好,可以防止脏读,但不能防止不可重复读,也不能防止幻读;
3.REPEATABLE READ(可重复读)(MySQL默认)
安全性较高,性能较差,可以防止脏读和不可重复读,但不能防止幻读问题;
4.SERIALIZABLE(串行化)
安全性最高,不会出现任何并发问题,因为它对同一数据的访问是串行的,非并发访问;性能最差;(不使用!!)