目录
1.为什么要有事务?(或者说事务的由来)
在人们日常生活中,转账是一件很平常的事,因为现在都用支付宝,微信瞬间就转过来了.不仅速度快而且扣住或者增加的金额都很准确.但在以前人们转账通常是用ATM机转账的,那个时候人们转完账之后,双方都要确定是否收到钱了,有可能会出现一边钱被扣除了,另一边没有收到钱的情况.这时候往往要去银行把钱追回来.所以为了解决这样的问题,我们就引入了事务.
2.什么是事务?
虽然引进了事务,但是事务到底是什么?
它的本质其实就是把原来多个sql语句打包成一个整体,多个sql语句构成的一系列操作要么都执行成功,要么都执行失败.就比如说上述的转账操作.account->表名,balance->要修改数据的名称.
update aacount set balance = balance -1000 where id = 1;
update aacount set balance = balance +1000 where id = 2;
本来是两条sql语句,可能会有一条语句执行成功,一条不成功.但是加上事务之后两条sql语句成为一个整体,只会出现执行成功和执行失败两种可能.这里的执行失败不是说一定没有修改过数据,而是可能修改过数据,但是因为另一个sql语句没有执行成功,又把修改后的数据给恢复了.这个恢复数据的操作成为"回滚"(rollback).
3.事务的特性
大致了解事务之后,我们来认知一下事务的几个关键特性:
1.原子性:事务能够一下执行完,不会说只执行一半
2.一致性:事务在执行前后的数据得是科学的,一致的.就比如说上面的转账操作,一方-1000那么另一方就得+1000,不能是别的数字,前后得一致.
3.持久性:事务对于数据的修改是持久的,是写到硬盘上的.简单来说就会事务执行完毕后,不能说重启服务器器后数据没变.
4.隔离性(重点!重点!重点!):
首先我们要了解一点.隔离性是为了去解决并发执行事务的问题.并发执行事务是因为数据库是服务器,但是很大概率是为很多个客户端服务的.所以说在同一时间可能会有多个客户端来修改数据.如果是修改不同的表和数据没啥事,但是一旦同时修改同一个数据就可能带来很多问题.而事务的隔离性就是来解决这些问题的.
问题1:脏读问题
用一个栗子来比喻一下脏读,比如说有一个同学A在考试的时候一道题不会想要看别人的答案,这个时候有个好心人B给他看了答案,但是这个答案呢是错的,好心人B在最后交卷的时候把这道题的答案给改了,但是他没有告诉这位抄他答案的A.最后就算A抄了答案也是错的.这个就是脏读问题,他获取到的数据是修改前还没有提交的数据,是一个无效数据.
事务解决脏读问题:
事务在修改数据时,将"写"(修改数据)这个操作进行了加锁.就是在修改数据的时候别人不能够读取这个数据.这个时候"读"和"写"不能同时进行,降低了效率但是提高了数据的准确性.
问题2:不可重复读问题
当你在读一篇文章的时候,读到一半,这个时候作者上线了,他觉得文章有的地方写的不好,就修改了文章的内容然后重新提交了.这就导致了你读文章读到一半发现文章内容突然变了.显然这是不科学的.我们读一篇文章应该读之前和读之后是一样的这叫可重复读,而如果中间发生了变化就是不可重复读的.
事务解决不可重复读的问题:
我们前面已经规定了给"写"加锁,而事务在解决不可重复读问题的措施是给"读"进行了加锁.就是一个客户端在"读"数据的时候别人不能"写"(修改数据).此时,进一步降低了效率提高了数据的准确性.
问题3:幻读
此时我们已经给"写"和"读"进行了加锁,但是俗话说天底下没有不透风的墙.还是上一个栗子,虽然我们规定了"读"的时候不能"写"(修改数据),但没说我不能"写"别的文章.所以这个时候作者又上线了,我另外再写一个文章,这个文章是你现在读的前传.在你读之前还没有这篇前传,但是在你读完文章后发现怎么又多了个前传.我是见鬼了吗?这种情况就叫幻读.
事务解决幻读问题:
那你非要在我"读"的时候搞点幺蛾子,那就别怪我心狠手辣了.此时数据库采用了"串心化"的方式来解决.就是我"读"的时候你不准干任何事情.你要操作必须等我完全操作完了之后才能操作.数据库这个时候就一个一个处理事务.此时执行的效率达到最低同时数据的准确性也是最高的.
脏读 -> 不可重复读 -> 幻读 在这个过程中并发的程度越来越低,到最后彻底串行化.
变化过程中的状态:
read uncommitted -> read committed -> repeatable read -> serializable
没有任何锁的限制 给"读"加锁 给"读"和"写"加锁 串行化
值得注意的一点是以上操作不能在数据库中通过代码实现,只能修改mysql数据库中的配置文件,来决定让数据库在那种状态下运行.