一、数据库事务
1.1、什么是数据库事务?
数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
意思就是一连串的数据库操作,即一串增删查改的集合。
1.2、数据库事务做了什么?
它把数据库从一个一致的状态转换到另一个一致的状态,比如数据库操作前是一个点,数据库操作后是一个点,
我们只管这两个点的状态,而两点之间的连线上的状态我们不管因为他们可能对我们想要的结果产生影响。
二、数据库事务四大特性(简称ACID):
2.1、第一个特性 原子性(Atomicity)
假如我们有个方法中对一个属性进行了N次的更新,但是执行到一半的时候有一个语句有问题出现了异常,这样就可能使得我们上面所说的操作后的点与我们预先的点不同,这不是我们想要的,所以原子性要求你这个方法要么全部执行成功,要么你就别执行。
2.2、 第二个特性 一致性(Consistency)
原子性中规定方法中的操作都执行或者都不执行,但并没有说要所有操作一起执行(一起更新那就乱套了,要哪个结果?),所以操作的执行也是有先后顺序的,那我们要是在执行一半时查询了数据库,那我们会得到中间的更新的属性?答案是不会的,一致性规定事务提交前后只存在两个状态,提交前的状态和提交后的状态,绝对不会出现中间的状态。
2.3、 第三个特性 隔离性(Isolation)
事务的隔离性基于原子性和一致性,每一个事务可以并发执行,但是他们互不干扰,但是也有可能不同的事务会操作同一个资源,这个时候为了保持隔离性会用到锁方案。
2.4、 第四个特性 持久性(Durability)
当一个事务提交了之后那这个数据库状态就发生了改变,哪怕是提交后刚写入一半数据到数据库中,数据库宕机(死机)了,那当你下次重启的时候数据库也会根据提交日志进行回滚,最终将全部的数据写入。
三、事务的隔离级别:
SQL标准规定了四种隔离级别,隔离级别由低到高分别为
- READ_UNCOMMITTED 读未提交
- READ_COMMITTED 读提交
- REPETABLE_READ 重复读
- SERIALIZABLE 序列化
另外,MySQL的默认隔离级别为REPETABLE_READ。
如果采用READ_UNCOMMITTED,可能会产生脏读、不可重复读、幻读的现象。
如果采用READ_COMMITTED,可能会产生不可重复读、幻读的现象。
如果采用REPETABLE_READ,可能会产生幻读的现象。
脏读(dirty read):A事务读取B事务尚未提交的更改数据,并在这个数据基础上操作。如果B事务回滚,那么A事务读到的数据根本不是合法的,称为脏读。在oracle中,由于有version控制,不会出现脏读。
不可重复读(unrepeatable read):A事务读取了B事务已经提交的更改(或删除)数据。比如A事务第一次读取数据,然后B事务更改该数据并提交,A事务再次读取数据,两次读取的数据不一样。
幻读(phantom read):A事务读取了B事务已经提交的新增数据。注意和不可重复读的区别,这里是新增,不可重复读是更改(或删除)。这两种情况对策是不一样的,对于不可重复读,只需要采取行级锁防止该记录数据被更改或删除,然而对于幻读必须加表级锁,防止在这个表中新增一条数据。
脏读/不可重复读/幻读解决方案:
脏读/不可重复读 使用行锁(悲观锁和乐观锁)解决,建议使用乐观锁,乐观锁更适合解决冲突概率极小的情况,而悲观锁则适合解决并发竞争激烈的情况。
幻读 使用表锁解决,防止新增一条数据。