Mysql的事务原理
什么事务
一组SQL语句(几句SQL),成批次的一起执行,要么全部成功,要么全部失败!
事务的ACID原则
原子性:(Atomicity)
一致性:(Consistency)
隔离性:(Isolation)
持久性:(Durability)
原子性
是指一个事务要么全部执行,要么完全不执行
例子:转账
包含了两个动作:
- A转账给B
200元
,:A 的余额 800 -> 600- B收到A的
200元
,:B 的余额 200 -> 400
一致性
事务在开始和结束时,始终应该满足一致性约束。
举例:还是一个转账汇款的例子。
A(
有800元
) 给 B(有200元
) 转账(A和B的总和应该为1000元
),一致性的约束条件的原则就是,在进行转账操作之后,A和B的总金额应还是1000元
持久性
一个事务结束后,所操作的数据,不会随着外界原因导致丢失
事务一旦提交,就不可逆转,即被持久化到了数据库文件系统中
- 事务没有被提交,那么就恢复到原来的状态
- 事务已经被提交,那么将数据持久化到数据库
举例:今天的王者荣耀的 "新品英雄抽奖券抽奖" ,在我点击抽奖时的一瞬间,匹配的对局也在这个时刻匹配到,弹出确认进入对话框,而此时我已经点击了抽奖的按钮,但却被对局开始而打断,领取奖励的页面并没有展现,随后对局结束后,查看背包内容,并没有得到相应的奖励,但是我的 "新品英雄抽奖券抽奖" 却依然在背包内,这一件事情,就完美的展现了事务的持久性。本例中的抽奖事务:点击抽奖按钮,奖券-1,奖励+1。然而,事务执行到,奖券-1后就被匹配而打断,奖励+1没有执行到,从而实现了抽奖事务的回滚,数据恢复到原状。
隔离性
一个事务的运行效果 不应该影响其他事务的运行效果。
但是却会存在隔离失败的情况,即随之而产生了隔离级别
数据库的隔离级别
脏读
一个事务,读取了另一个事务未提交的数据。
举例:转账问题
A :100元 B:200元 C:100元
事务a:A转账给B->50元,A -> 100-50=50元,B -> 200+50=250元
事务b:C转账给B->100元,此时B应该变为350元,但是在
事务a
未提交时,读取到B的余额是200元,则B:200+100=300元。而正确的情况应该是,获取到B的最新数据:250元,进行事务b
的执行,进而B:250+100=350元。
不可重复读
在一个事务范围内,两次相同的查询却返回了不同的数据(有时候可能不是错误的查询)
通俗的说:
某一学生的当前成绩为:200分
事务a:读取该学生的总成绩
事务b:该学生的总成绩增加100分
事务a:执行第一次查询:100分,为了校验成绩,本事务里包含了两条相同的查询,而在进行第二次校验查询时,事务b增加100分对学生的总成绩,导致了,第二次的校验查询所得到的成绩结果是200分。但并不是读取错误
幻读
指在一个事务内,读取到了另一个事务新增的数据,导致了前后读取的不一致(表现为数据总条数多了一行)
通俗的说:
某班级学生分数统计:共1名学生
事务a:读取该班级所有学生的成绩
事务b:新录入了一个学生的成绩
事务a:前后读取的总数居条数产生了不一致,即为幻读