1.什么是事务
事务是指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败(通俗的说一组SQL语句,要么全部执行成功,一条语句出错则全部出粗);在不同的环境中,都可以有事务,对应在数据库中,就是数据库事务.
2.为什么使用事务
事务的核心逻辑就是多条SQL语句要么全部执行成功,要么全部不执行;
举个例子:假如A公司给B公司转账1000w,转账执行到一半的时候,A公司的系统遭遇了崩溃(如网络错误或者数据库挂掉了),造成A公司的转账出现错误,此时A公司的账户就会少1000w,但是B公司的账户并不会增加1000w,其中B公司账户没有增加的原因就是事务发挥了作用,此处A公司转账的操作就相当于一个事务;
3.事务的使用
(1) 开启事务:start transaction;
(2) 执行多条SQL语句;
(3) 回滚或提交:rollback/commit.
rollback即是全部失败,commit即是全部成功.
每条SQL语句执行的结果都会被记录,一旦某一条SQL语句执行出错,就会进行回滚,将之前SQL语句执行后的结果回滚成开始的结果,如果多条SQL语句全部执行成功,就会将这么多条SQL语句执行的结果打包提交.
4.事务的特性
事务有4个特性:
原子性(事务的初心):即多条SQL语句要么全部成功,要么全部失败;
一致性:即事务执行前后的数据都是合法数据,例如转账操作,转账过程中如果出错的话,钱不能丢失;
持久性:即事务执行之后产生的修改都会被写入到硬盘,及时程序重启/掉电,事务都可以正常工作;
隔离性:即在并发过程中,多个事务之间的"相互影响程度"(着重讲解).
隔离性:
如果隔离性越高,事务之间的并发程度越低,执行效率越慢,但是数据的准确性越高;
如果隔离性越低,事务之间的并发程度越高,执行效率越快,但是数据的准确性越低.
MySQL给我们提供了不同的"档位"(可以控制隔离性的高低/并发程度的高低/执行效率的高低/数据准确性的高低),即MySQL的隔离级别,我们将举一个例子来详细介绍MySQL的不同隔离级别.
1."脏读"问题
假如老师在电脑上写代码,一个学声跑过来看老师写代码,发现老师写一个Student类(此时老师相当于事务A在写数据,学生相当于事务B在读数据),学生在看完老师的代码之后就走了,突然老师觉得Student这个类不好,换成了Animal这个类,此时学生读到的数据就是一个错误的数据,这就是"脏读"问题;这种情况事务A和事务B是完全并发的,没有任何限制,也是隔离性最低的情况.
2."不可重复读"问题
为了解决"脏读"问题,我们就需要给写操作"加锁"(就是老师在写代码的时候学生不准看,必须得等到老师将代码提交了之后才可以看),此时就降低了并发性,提高了隔离性,读取到的数据的准确性就会提高;假如学生读取的时候,老师将代码又修改了重新提交,此时造成学生两次读取的数据是不一样的,这就是"不可重复读"问题.
3."幻读"问题
为了解决"不可重复读"问题,我们就需要给读操作"加锁"(就是学生在读数据的时候不可以对学生读的数据进行修改),此时又进一步的降低了并发性,提高了隔离性,读取到的数据的准确性又得到了提高;假如老师又写了一份代码进行了提交,学生发生提交的目录增加了一个,这就是"幻读"问题.
4.串行化
为了解决"幻读"问题,我们就需要严格按照串行化来执行(就是老师在写数据的时候学生不能读数据,学生要读数据的时候老师不能写数据),此时并发程度最低,隔离性最高,数据最准确.
MySQL的隔离级别
read uncommitted
不做任何限制,事务之间都是随意并发执行的,并发程度最高,隔离性最低;会产生脏读+不可重复读+幻读问题.
read committed
对写操作加锁了,并发程度降低了,隔离性提高了;解决了脏读问题,会产生不可重复读+幻读问题.
repeatable read
对写和读操作都加锁了,并发程度又降低了,隔离性又提高了;解决了脏读+不可重复读问题,可能存在幻读问题.
serializable
严格串行化,并发程度最低,隔离性最高;解决了脏读+不可重复读+幻读问题,执行速度最慢.