1、事务的认识
事务:事务就是将多个SQL给打包在一起,组成一个整体。组成这个整体的各个SQL,要么全部成功,要么全部失败。
举例说明:
情人节到了,滑稽老铁打算给他女朋友小美发给红包,但是他又害怕小美不收,于是他想到了一个办法就是通过银行卡进行转账。他给小美转账了 520
元,那么滑稽老铁的银行卡余额就得 -520 元,小美的银行卡余额 +520 元。这些操作就组成一个整体,就变成了事务,要么执行,要么就一个都不执行。
如果中间出错了,就一条都不执行。这里的一条都不执行,并不是真的一条都不执行,而是自动的恢复成执行之前的样子了,看起来就好像一个都没有执行一样,这个操作就称为“回滚(rollback)”。
回滚:回滚就是把执行过的操作逆向恢复回去,就像电脑上的 ctrl + z 操作
数据库会把执行的每个操作都记录下来,如果某个操作出错了,就会把事务中前面的操作进行回滚,然后根据之前进行的操作,进行逆操作
这些操作是会有很大开销的,可以保存但不能无限保存,最多就是把正在执行的事务保存下来,额外的东西不好再保存了
2、事务的特性
2.1事务的四大特性
*
原子性:打包成整体这个操作,就称为“原子性”,这个是事务最核心的特性
举例说明:滑稽老铁给小美转账 520 元,此时滑稽老铁余额 - 520 元,小美余额 +520,此时把转账、滑稽老铁余额 - 520 元,小美余额
+520元 打包成一个整体,要么都执行,要么一个都不执行,这就具有了原子性。
*
一致性:事务执行前/执行后,都得是数据合法的状态
举例说明:滑稽老铁给小美转账520元,如果转账成功滑稽老铁余额-520元,小美余额+520元。如果转账失败滑稽老铁余额不扣钱,小美余额也不加钱。
注:一致性是根据原子性而来的,要么全部执行,要么都不执行
*
持久性:事务产生的修改,都会写入硬盘
举例说明:滑稽老铁给小美转账 520 元,转账成功滑稽老铁余额-520元,小美余额+520元,这个是持久的,不会改变的。
*
隔离性:一个数据库服务器,同时执行多个事务的时候,事务之间的“相互影响程度”
举例说明:当多个事务同时执行的时候,一个事务的执行是否会干扰到其他事务,这就是事务的隔离性
2.2 隔离性的重点说明
MySQL
服务器,是要同时给多个客户端提供服务,此时多个客户端之间就可能会同时发生事务,尤其是这多个事务在操作同一个数据库的同一个表的时候,就可能引起一些麻烦
*
如果隔离性越高,也就意味着事务之间的并发程度越低,执行效率越慢,但数据的准确性越高
*
如果隔离性越低,也就意味着事务之间的并发程度越高,执行效率越快,但数据的准确性越低
2.3 事务同时执行会出现的问题
2.3.1 脏读
脏读:当事务A在写数据的时候,事务B读取事务A写的数据,事务B 读完后,事务A改了数据,那么此刻事务B读到的数据就是错误的数据,这就称为“脏读”问题。
举例说明:张三和李四是同桌,有一次老师布置课堂作业的时候,李四第二题不会写,于是李四就偷偷的看了一眼张三写的,看到张三第二题选了A,
在这个场景下,滑稽老铁和小美这两个事务是完全并发的没有任何限制,在这个前提下就会出现脏读问题
问题:如何解决脏读问题?
答:解决脏读问题就是降低并发性、提高隔离性,可以给这里的 "写操作" 进行加锁
加锁:当进行了写加锁,滑稽老铁在制定表白计划表的期间,别人就不能同时去读了。相当于降低了并发程度,提高了隔离性,降低了一定的效率,但是提高了准备性
2.3.1 脏读
脏读:当事务A在写数据的时候,事务B读取事务A写的数据,事务B 读完后,事务A改了数据,那么此刻事务B读到的数据就是错误的数据,这就称为“脏读”问题。
举例说明:张三在写作业,作业内容 123+32 = 15.. 当张三写完 15
之后,李四跑过来瞄了一眼张三的答案:123+32=15,于是李四就把这个答案抄到自己的作业本上了,但是实际上张三要写的是 123+32 =
155,但是李四读到了一个张三还没写完的答案,也就导致李四读到了一个错误的数据,这就是脏读问题
如何解决脏读问题呢?
答:降低并发性、提高隔离性,也就是给“写操作”加锁
加锁可以分为:写加锁和读加锁
写加锁:写的时候,别人不能进行读
读加锁:读的时候,别人不能进行写
2.3.2 不可重复读
不可重复读:事务B 在读的时候,事务A改了数据,此刻事务B连续两次读到的数据结果不一样
举例说明:张三在写作业的时候,发生李四一直在瞄。张三感觉李四有点影响到他了,于是就跟李四约定,等张三写完了再给李四瞄。过了一会张三写完了,李四就开始瞄了,当李四正在瞄的时候,张三发现自己有个地方错了,就李四等一会再瞄,自己先改一下,这就导致李四之前瞄到的数据和现在瞄到的数据可能不一样
如何解决不可重复读呢?
答:给读加锁,让李四读的时候,张三不能修改。
这两个事务之间的并发程度进一步降低了,隔离性又进一步提高了,运算速度又进一步变慢了,数据的准确性又进一步提高了
2.3.3 幻读
幻读:事务A写的时候,事务B不能读;事务B读的时候,事务A不能写。虽然事务A不能写,但是事务A可以新增和删除一个其他的文件,此刻事务B
两次读到的结果集就不同了
李四正在瞄的时候,张三让他等一下在喵,自己先改一下。李四感觉自己正在瞄的时候,张三总是打断自己,于是就跟张三商量说,你写的时候我不去瞄,我瞄的时候你也不能让我等一下你去改。于是张三就跟李四约定好了,张三写的时候李四不能读,李四读的时候张三不能写。李四在瞄的时候,张三没事干,张三就看哪里写错了,发现写错了自己又不能在李四读的时候去改,然后就把正确答案写到另一种本子上,写完后把正确答案在拿出来,李四一看怎么又多了本子,这就是幻读问题
如何解决幻读问题?
答:串行化,彻底的舍弃并发。就是当事务B读的时候,事务A什么都不能干
3、MySQL提供的隔离级别
MySQL 为了解决并发执行带来的问题,提供了四个隔离级别
*
read uncommitted:不做任何限制,事务之间都是随意并发执行的。并发程度最高,隔离性最低。会产生: 脏读+不可重复读+幻读
*
read committed:对写操作加锁,并发程度降低了,隔离性提高了。解决了脏读问题,但仍然存在:不可重复读+幻读
*
repeatable read:对写和读都加锁了,并发程度又降低了,隔离性又提高了。解决了脏读和不可重复读问题,但可能存在:幻读
*
serializable:严格串行化,并发程度最低,隔离性最高。解决了脏读+不可重复读+幻读问题,但执行速度最慢