前段时间在写一个商城项目的卡券兑换功能时,发生了一个小小的bug。卡券兑换的逻辑应该是先验证,验证通过后卡券兑换,然后把卡券设置成已使用。因为项目才刚上线,并且开发工期紧,所以代码就直接这么上线了。然后因为其他的原因,导致RDS高并发处理变慢,然后用户多次点击后导致卡券充值多次的情况。后来,我们项目组开发组长说加个事务来预防这种问题。之前也了解过事务,但是了解的一知半解,因为之前公司的项目也没有用到这些,这次正式碰到了,就去网上了解了一下这方面的相关知识。
下面主要介绍一下mysql事务的的隔离级别以及会造成的各种影响
mysql中,innodb所提供的事务符合ACID的要求,而事务通过事务日志中的redo log和undo log满足了原子性、一致性、持久性,事务还会通过锁机制满足隔离性,在innodb存储引擎中,有不同的隔离级别,它们有着不同的隔离性。
隔离级别:可重复读 下面我们用实战来演示一下 我们建一张user表,里面又account,password字段。

我们现在这里面插入两条数据,如图。下面我们打开两个命令行界面,来演示两个事务之间的相互影响。








数据也没有发生变化!
下面介绍一下 这种隔离级别下出现的一种幻读的情况,接下来我们继续开启两个命令行界面,开启两个事务。

我们在第一个事务中插入一条数据


接下来我们在第二个事务中更新数据

这个时候再去查找的时候多了一条数据,这就是在“可重读”情况下出现的幻读现象。
隔离级别:串行化 我们再开两个命令行界面,把隔离界别改成串行化,表还是用之前的那张表



当在事务2中执行查询语句时,查询被阻塞,此时事务1被提交,当事务1被提交后的一瞬间,事务2中的语句已经查询出结果,从返回结果可以看出,这个查询语句被阻塞了31秒左右的时间,当事务1中的写锁释放时,事务2才读出了数据。从上述实验上来看,当事务处于串行化隔离级别时,是不可能出现幻读的情况的,因为如果另一个事务中对表添加了写锁,那么在当前事务中是无法读到数据的,必须等到另一个事务提交,另一个事务释放了对表的写锁,当前事务才能进行申请读锁,使用串行化的隔离级别不会出现幻读的情况,但是,聪明如你一定发现了,当事务的隔离级别设置为串行化时,数据库失去了并发的能力,所以,我们很少将隔离级别设置为串行化,因为这种隔离性过于严格了。
还有两种隔离是“读未提交”和“读已提交”,这两个隔离比较简单。顾名思义,读未提交就是在一个事务中操作了数据,事务不用提交就在另一个事务中读到;“读已提交”在一个事务中操作了数据,提交后就能在另一个事务中读到。