事务
ACID
4个特性:一致性,持久性,隔离性,原子性
1.一致性
不论事务成功还是失败,你的业务应该是一致的,数据不能被损坏。比如转账,你给张三转了1000,结果代码出错了,你扣了1000,但张三没有收到1000,这样数据/业务就损坏了,违反了一致性。应用系统从一个正确的状态到另一个正确的状态.而ACID就是说事务能够通过AID来保证这个C的过程.C是目的,AID都是手段. consistency
2.持久性
事务一旦完成,结果永久生效,无法回滚。durability
3.隔离性
多个事务同时处理一份数据时,事务之间应该相互隔离,否则就乱了(跟线程安全有点类似)。isolation
4.原子性
整个方法被捆绑成一个原子,不可拆分,要么一起成功,要么一起失败(同生共死)。 atomicity
并发事务引起的安全问题
1.脏读
A事务读取了B事务未提交的数据(一旦B事务回滚,可能会导致A事务读取的数据无效)。
2.不可重复读
一个事务方法中连续查询多次,却得到不同的结果(原因:并发事务在两次查询的中间对数据进行了修改)。
eg. 事务1:查询一条记录
-------------->事务2:更新事务1查询的记录
-------------->事务2:调用commit进行提交
事务1:再次查询上次的记录
***此时事务1对同一数据查询了两次,可得到的内容不同,称为不可重复读
3.虚读/幻读
一个事务方法中连续查询多次,却得到不同的结果(原因:并发事务在两次查询的瞬间对数据进行了增删)。
eg. 事务1:查询表中所有记录
-------------->事务2:插入一条记录
-------------->事务2:调用commit进行提交
事务1:再次查询表中所有记录
***此时事务1两次查询到的记录是不一样的,称为幻读
数据库4个隔离级别
安全性从低到高:唯一可穿
1.未提交读
安全级别最低,3个安全问题都解决不了。
2.已提交读(Oracle默认)
可以解决第一个问题(脏读)。
3.可重复读(mysql默认)
可以解决前两个问题(脏读和不可重复读)。
4.串行[又叫可序列化]
全部解决。
注意1:安全级别越来越高,那么效率就越来越低。比如串行,虽然把3个问题全解决了,但是有代价,它在执行A事务的时候,把整张表锁定,不论是读事物还是写事物,全都串行排队。
注意2:数据库的隔离级别可以修改,但一般采用默认,不过有人为了提高mysql的性能,将其隔离级别改为第二级(已提交读),由于间隙锁的优化策略的存在,解决了不可重复读和虚读/幻读。
事务的传播
事务的传播:一个事务方法调用另一个事务方法,必须指定事务如何传播(比如:一个service方法调用另一个service方法)。
注:事务的传播行为看的是被调用的方法,方法被调用的时候,就会触发事务的传播。
(1) REQUIRED(spring默认)
调用方有事务就用它的,没事务就用自己的
(2) REQUIRED_NEW
在事务方法调用过程中,把调用方的事务挂起,使用自己的事务。
(3) SUPPORTS
当前有事务就用,没事务就拉倒(不用)
(4) NOT_SUPPORTED
不支持事务,当前有事务就挂起
(5) NESTED
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
(6) NEVER
以非事务方式运行,假设当前存在事务,则抛出异常
(7) REQUIRES_NEW
新建事务,假设当前存在事务。把当前事务挂起