目录
一、什么是事务?为什么需要事务
二、事务的四大特性(ACID)
三、事务的使用
四、并发带来的问题
1、脏读问题
2、不可重复读
3、幻读
五、MySQL的隔离级别
一、什么是事务?为什么需要事务
事务的概念:
事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败。
在不同的环境中,都可以有事务。对应在数据库中,就是数据库事务。
举个例子:
小明和小红约好逃课去看英雄联盟总决赛。现在有三个步骤:
- 小明逃课
- 小红逃课
- 一起去看总决赛
但小明逃课出来等小红的时候,发现小红被老师逮住了,所以小明叹气地说:那还不如我不逃课,在教室上课呢!
此时事务地重要性就体现出来了,事务就是把这几个操作打包成一个整体,要么都执行成功,要么一步都不执行(结果要么我们去看了总决赛,要么我们都在教室上课),这就是事务的概念
二、事务的四大特性(ACID)
- 原子性(automicity):事务中的若干操作要么全部执行成功,要么全不执行
- 一致性(consistency):在事务开始之前和结束之后,数据库的数据都要合理合法
- 隔离性(isolation):数据库允许多个并发事务同时对数据进行读写和修改,隔离性可以防止多个并发任务交叉执行导致数据不一致
- 持久性(durability):事务一旦执行完毕,那么对于数据的修改就是持久生效的(存到磁盘)
事务的原子性如何保证:
原子性要求的是要么全不执行,要么执行成功,但在我们执行到某一个sql之前,我们是不知道它能否执行成功的,那么我们还如何保证原子性呢?
当出现执行失败时,由数据库执行”还原“操作,消除之前执行SQL带来的影响,对外而言就像从未执行一样!
这种”还原“操作就被称为”回滚“(rollback)
三、事务的使用
开启事务:
start transaction;
执行SQL语句:
.............................
回滚或提交:
rollback/commit;
start transaction;
// transaction 与 commit 之间,就是事务中的若干操作
-- 阿里巴巴账户减少2000
update accout set money=money-2000 where name = '阿里巴巴';
-- 四十大盗账户增加2000
update accout set money=money+2000 where name = '四十大盗';
commit;
四、并发带来的问题
并发编程是如今越来越流行的一种编程方式,并发式执行能够大大提升我们的代码运行速度
并发虽好,但可苦了数据库!!!
数据库在并发执行多个事务时,修改 / 读取的数据是同一个数据时就会出现问题。事务的隔离性就是为了解决以上问题,因此这里我们谈一下并发执行所带来的问题
1、脏读问题
脏读是指在事务A在执行修改数据的操作时(事务A还没操作结束),另一个事务B读取了数据库的内容,此时事务B的读操作就是脏读。
举个例子:
A和B在同一个考场考试,B什么都不会,一直在瞅A的卷子,B抄的很开心,兴冲冲的交了卷子,就在这时,B发现A把卷子上的答案修改了,B留下了悔恨的眼泪~~
脏读的解决方法:
出现脏读的原因就是事务和事务之间没有任何隔离,那我们加上一些约束限制,就可以有效避免出现脏读——给写操作加锁,当一个事务在执行写操作时,其他事务没法执行读操作,当事务执行完毕后释放锁,其他事务才能读
2、不可重复读
不可重复读就是事务在执行过程中,多次读取到数据不相同
引用Dark And Grey大佬一张好图:
不可重复读的处理方法:
首先思考不可重复读出现的原因——在另一个事务B执行读操作的同时,我们事务A还在修改数据,这就导致数据B在事务中每一次读到的数据是不一样的。那么处理方式就比较简单:在我读的时候,你不能修改。也就是给读操作上锁。
3、幻读
幻读就是事务A在执行过程中,多次读取的结果集不一样(数据总量不一样)虽然读操作和写操作都加锁了,但可以新增数据
引用Dark And Grey大佬一张好图:
幻读的解决方法:
首先思考幻读出现的本质就是我们为了提升效率,在读者看我们第一篇博客的时候我们已经在卷第二篇博客了,所以解决的本质就是串行化执行,当读者在阅读我们的博客时,我们放弃写博客,直到读者读完。简单来说就是一个一个来,出来一个事务,解决一个事务。
这种执行方式的隔离性最高,但并发性最低,数据最可靠,速度很慢
常言道:鱼与熊掌不可兼得,隔离性和并发也是如此,又想执行速度快,又想隔离执行数据最准确,这是不可能的,我们必须在 ”快“ 和 ”准“ 之间找到一个平衡点。
五、MySQL的隔离级别
- read uncommited 允许读取未提交的数据,隔离性最低,并发性最高,存在脏读的问题
- read commited 只允许读取已提交的数据,对写操作加锁,隔离性提高了,并发性降低了,存在不可重复度和幻读
- repeatable read 给读操作也加锁了,这是MySQL 的默认隔离级别,解决了不可重复读,但存在幻读
- serializable 严格的串行化执行,隔离性最高,解决了幻读问题