一、引出事务
假设我们有一张用户表,如图所示:
我们现在的需求是:小红向小明转账100块
那么我们可以执行如下指令:
update user set salary = salary-100 where id=1;//第一条语句小红转一百
update user set salary = salary+100 where id=2;//第二条语句小明收一百
但是如果我们执行第一条语句结束,执行第二条语句的时候失败,那么就会造成小红的salary=400,而小明的salary=100,当资金数额巨大,这样就会造成重大事故,原因就是我们的第一条和第二条语句不是一起执行,不是一个原子操作(要么全做,要么全不做)。那么我们的事务就可以解决这类问题。
二、事务
1、概念
事务用于保证数据饿一致性,它由一组相关的DML(插入、修改、删除)语句构成 ,该组的DML语句要么全部成功,要么全部失败。
2、事务与锁
当执行事务操作时(DML语句),MySQL会在表上加锁,防止其它用户改变表的数据,这对用户来说很重要。
3、事务基本语句和操作流程
事务中的基本操作
①start transaction : 开启一个事务;
②savepoint 保存点名称 :设置保存点;
③rollback to 保存点名称 :回退事务;
④rollback : 回退全部事务;
⑤commit : 提交事务,所有的操作生效,不能回滚。
事务基本操作流程
如上图所示,我们在A点开启了事务,设置了保存点B、C,分别执行了三个DML操作,当前程序处在D点。假设我们觉得第三个执行的DML操作有问题,那么我们这时可以通过rollback to到保存点C重新执行我们的程序,此时数据库中保存的数据就是C之前的数据,当然也可以回滚到A点或者回到开启事务的地方(注:此时在这之前的保存点的消息全都被删除了)。
案例展示:
先执行如下操作:
#1、创建一张表
create table t
(id int ,
`name` VARCHAR(45)
);select * from t;#2、开始事务start TRANSACTION#3、设置保存点aSAVEPOINT a;#4、执行dml操作INSERT into t VALUES("1","张三");#设置保存点bSAVEPOINT b;#执行dml操作INSERT into t VALUES("2","李四");
此时数据库中数据:
再执行以下指令:
#退回到bROLLBACK to b;#退回到aROLLBACK to a;#回退全部事务,直接回退到事务开始的状态ROLLBACK#提交事务COMMIT
分别得到回退到b:
回退到a:
全部事务回退:
事务提交后:
若想回退到b
4、事务的细节
①:如果不开启事务,在默认情况下,DML操作是自动提交的。不能回滚的;
②:如果开启一个事务。你没有创建保存点。你可以执行rollback,默认返回到开启事务的状态;
③:在事务还未提交时,可以设置多个保存点;
④:MySQL的事务机制需要innodb的存储引擎才可以使用,MyISAM存储引擎不好使用;
⑤:开启事务start transaction,关闭事务set autocommit=off.
三、事务的隔离级别
1、概念
多个连接开启各自的事务操作数据库中的数据时,数据库系统要负责隔离 操作,以保证各个连接在获取数据时的准确性。
假如有两个客户端Client1与Client2同时对我们数据库的user表进行操作,假设Client1对user表执行DML操作,而Client2在对user表执行查看操作,此时设置不同的隔离级别,Client2便会看到不同的数据。
2、不考虑隔离级别,可能出现情况
(1)脏读
事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据。(读取到别人未提交的数据)
(2)不可重复读
事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交(主要是修改或删除),导致事务A多次读取同一数据时,结果不一致。
如图所示,假设事务A在8:00开始读取数据,读取8:00之前的数据,此时,8:01时事务B登录了数据库并对数据库执行了DML操作,而此时A却看到了B中对数据的操作,此时出现了不可重复读,因为A还未Commit提交结束的话,是不应该看到B的操作的。
(3)幻读
系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录(主要是插入操作),当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
3、事务隔离级别
①未提交读: 最低的隔离级别,允许读取尚未提交的数据变更,可 能会导致脏读、幻读或不可重复读。
②已提交读: 允许读取并发事务已经提交的数据,可以阻止脏读,但是 幻读或不可重复读仍有可能发生。
③可重复读: 对同一字段的多次读取结果都是一致的,除非数据是被本身 事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
④可串行化: 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐 个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读 以及幻读
使用隔离级别之前一定要开启事务!!!
说明:√表示可能出现,×表示不可能
事务隔离级别 | 脏读 | 不可重复读 | 幻读 | 加锁读 |
读未提交(read-uncommitted) | √ | √ | √ | 不加锁 |
读提交(read-committed) | × | √ | √ | 不加锁 |
可重复读(repeatable-read) | × | × | × | 不加锁 |
串行化(serializable) | × | × | × | 加锁 |
四、MySQL事务的ACID
①原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操 作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。
②一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。
③隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能 向这张卡转账。
④持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。
五、总结
到了最后做一个总结吧,这篇文章应该是把事务的大多数知识点做了一个总结,对于一些面试题的知识点也是涉及到了的,而且对于一些比较难理解的地方。博主也是举例和图表相结合的形式进行阐述,如果觉得对屏幕前小伙伴有所帮助,不要忘点赞+关注一波哦!后期还会有更多的内容的饿呈现!