友情提醒
先看文章目录,大致了解文章知识点结构,点击文章目录可直接跳转到文章指定位置。 |
数据库:按照数据结构来组织、存储和管理数据的仓库
事务:指具体的事情、杂务。
数据库事务:简单的说就是对数据库访问并可能进行操作的一系列行为。
事务具有4个特征,分别是原子性、一致性、隔离性和持久性,简称事务的ACID特性
①原子性
原子是指化学反应不可再分的基本微粒,原子性指一个事务要么全部提交成功,要么全部失败回滚,不能分割执行其中的操作
②一致性
指事务的执行不会破坏数据关系的完整性和业务逻辑的完整性。
比如一位老人家在银行存了一千万块,他把钱取出来一百万过过眼瘾又存回去。这个存取的事务执行过程不会让钱(数据)变多或者变少,也就是不会破坏数据完整性。
③隔离性
一个事务不会被另一个事务影响,最好的情况是第一个事务执行完成后再执行另一个事务,但处于性能上的考虑,一般都需要事务并发执行操作相同的数据,这时就要求一个事务内部的操作及使用的数据不被其他事务干扰,例如不能读取到另一个未提交事务写入的值。
④持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。隔离级别是一个事务所能看到其他事务中修改的数据的程度,允许事务受不同程度的干扰,这个程度分为四级,我们称为事务的四种隔离级别,每种隔离级别都可能带来不同的数据问题。
①读未提交 : 在该隔离级别,所有的事务都可以看到其他事务没有提交的执行结果。但是相当于没有任何隔离性。
②读已提交 :该隔离级别是大多数数据库的默认的隔离级别(不是 MySQL 默认的)。它满足了隔离的简单定义:一个事务只能看到其他的已经提交的事务所做的改变。这种隔离级别会引起不可重复读。
③可重复读: 这是 MySQL 默认的隔离级别,它确保同一个事务,在执行中,多次读取操作数据时,会看到同样的数据行。
④可串行化 : 通过强制事务排序,使之不可能相互冲突,解决了幻读的问题。它在每个读的数据行上面加上共享锁。(实际中基本不使用)
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读已提交 | 可能 | 可能 | 可能 |
读未提交 | 不可能 | 可能 | 可能 |
可重复读 | 不可能 | 不可能 | 可能 |
可串行化 | 不可能 | 不可能 | 不可能 |
①脏读:当一个事务读取到另外一个事务修改但未提交的数据时,就可能发生脏读。例子:事务二修改了数据,但是没有提交,事务一读了这个没有提交的数据。如果事务2回滚了刚才的修改或者做了另外的修改的话,事务1中查到的数据就是不正确的了,所以这条数据就是脏读。
事务一 | 事务二 |
---|---|
查询了一次获得结果一 | / |
/ | 修改了数据,但是没有提交 |
再次查询得到了结果二 | |
/ | 回滚成功 |
②不可重复读:就是说,比如在A事务中进行多次相同的查询,B事务在A事务多次查询之间修改对应表中的数据,导致A事务多次读取的结果不一致。例子:事务二提交事务,因此他的修改就对其他事务可见了。导致了事务一进行相同查询两次结果不一致,这就是不可重复读。
事务一 | 事务二 |
---|---|
查询了一次获得结果一 | / |
/ | 修改了数据,得到结果二,提交成功 |
再次同样查询得到了结果二 |
③幻读是’‘不可重复读’'的一种特殊场景:例子:事务一将表中性别列的值都更改为1,事务二又添加了一条"性别”的值为0记录,事务一再查询所有的记录时会发现有多了一条记录的“性别为0,这种情况就是所谓的幻读
事务一 | 事务二 |
---|---|
性别列值都改为1 | / |
/ | 添加了性别为0的记录 |
再次查询发现新增了一条性别为0的记录 |
ps:不可重复读与幻读区别
不可重复读针对:update
幻读针对:delete,insert
什么是事务的传播行为:事务传播行为用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法时,事务如何传播。
PROPAGATION REQUIRED 表示当前方法必须在一个具有事务的上下文中运行,如有客户端有事务在进行,那么被调用端将在该事务中运行,否则的话重新开启一个事务。(如果被调用端发生异常,那么调用端和被调用端事务都将回滚)
PROPAGATION SUPPORTS 表示当前方法不必需要具有一个事务上下文,但是如果有一个事务的话,它也可以在这个事务中运行
PROPAGATION MANDATORY 表示当前方法必须在一个事务中运行,如果没有事务,将抛出异常
PROPAGATION REQUIRES NEW 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
PROPAGATION NOT SUPPORTED 总是非事务地执行,并挂起任何存在的事务。
PROPAGATION NEVER 总是非事务地执行,如果存在一个活动事务,则抛出异常
PROPAGATION NESTED表示如果当前方法正有一个事务在运行中,则该方法应该运行在一个嵌套事务中,嵌套的事务可以独立于被封装的事务中进行提交或者回滚。如果封装事务存在,并且外层事务抛出异常回滚,那么内层事务必须回滚,反之,内层事务并不影响外层事务。如果封装事务不存在,则同propagation.required的一样