小钢同学今天发工资了,赶紧打开招商银行app看看工资到账了没有,查看余额300
嗯,今天心情好,给对象转账50大元买lv包包去,最后的结果肯定是小钢同学的钱包余额是250,小钢同学对象钱包余额+50
转账的整个过程在mysql中涉及到一系列动作,下面仔细来看看
现在来考虑一下这个问题,如果在第6步的时候更新数据库失败了会发生什么情况?
首先得注意的是并不是所有的mysql存储引擎都支持事务,常见的Innodb是支持事务的,而MyISAM则不支持事物,所以mysql默认的存储引擎是Innodb
事务有以下四大特性:
比如文章开头所说的小钢转账问题,如果中间任何一个步骤出现问题,事务需要回滚到最初始状态,就好比没发生这件事情一样
小钢给对象转账之前,小钢余额300元,对象余额0元,总和300元;
小钢给对象转账50元以后,事务提交完成,小钢余额250,对象余额50元,总和300元
转账前和转账后总和不变,这就是一致性
事物提交后,小钢余额250,对象余额50元,这个数据是一个持久性的状态,除非再次修改
mysql事务核心在于隔离性,本文重点讲解一下隔离性
首先还是谈一下事务并发会带来什么问题?
事务A和事务B同时开始执行,事务A先读取小钢余额是300元,事务B紧接着将小钢余额更新为250元,此时事务B没有提交事务,事务A在这个时候再次查询小钢余额发现变成了250元,此时事务B提交事务失败回滚了,小钢余额变为了初始300元,事务A却还认为小钢余额为250元,此时事务A读到的250元数据就是脏数据
事务A和事务B同时开始执行,事务A读取小钢余额300元,然后先去干其他事情了,事务B读取小钢余额300元并更新为250元,然后成功提交事务,此时事务A再次读取小钢余额为250元,在同一次事务执行中读取数据不一致,这就是不可重复读问题
事务A和事务B同时执行,事务A负责将所有工资等于100元的员工工资加薪到200元,比如此时有5个员工需要加薪,事务A完成了更新操作,但是还未提交事务,事务B此时新增一个新员工的数据工资为100元,然后提交事务,然后这个时候事务A再次查询工资等于100元的员工,发现变成了6个员工,就好像发生了幻觉一样,这就是幻读
事务四种隔离级别
会发生脏读、不可重复读、幻读
会发生不可重复读、幻读
会发生幻读
可以解决所有事务并发问题
那么可能会有一个问题,为什么可串行化可以解决所有事务并发问题,为什么数据库不用可串行化隔离级别?
原因:可串行化需要加锁,太慢了,对于优秀的开源系统怎能容忍这种效率问题
mysql默认的隔离级别是可重复读,虽然有幻读的风险,但是概率并不大
mysql的可重复读就是巧妙的借用了MVCC多版本并发控制的思想