以下用到的例子是:银行存取款等场景
脏读
概念
A事务读取B事务尚未提交的数据并在此基础上操纵,而B事务执行回滚操作,那么A读取的数据就是脏数据
场景讲解
小张媳妇去取款买衣服,9点去ATM机器查询余额是:1000元,这个时候小张发工资了,按时上交,小张也去ATM存现金,小张媳妇是9点查询,9点十分取了500,余额还剩500,这个时候小张查询余额就是500元,但是突然ATM机器在小张媳妇马上要拿钱的时候,现金不够了,导致余额恢复到了1000元,这个时候小张又存了100,在小张眼里,余额现在是600元了,就造成了小张查询余额的时候,读取的是小张媳妇看似取款了但最后没有取款成功的余额,这就是脏读
图解
时间 | 小张存款事务A | 小张媳妇取款事务B |
9:00 | 开始事务 | |
9:05 | 开始事务 | |
9:10 | 查询账户余额是:1000元 | |
9:15 | 取款500,账户余额被修改为500元 | |
9:16 | 查询账户余额:500元(这就是脏读,因为小张媳妇的取款动作没有彻底结束) | |
9:17 | ATM没现金了,没办法取款,扣除的500要归还到原始账户,现在余额是:1000元(回滚,事务结束) | |
9:18 | 存入1000元,查看账户余额是:1500元 | |
9:19 | 确认操作,拔出银行卡(提交事务) |
这就导致到最后核对的时候,小张说他自己存了1000,余额是1500,小张媳妇看到的是1000,小张媳妇可能就会怀疑小张再戏弄她,说不定回家就让小张跪搓衣板,哈哈哈哈
不可重复读
概念
事务A重新读取前面读取过了的数据,发现该数据已经被另一个已提交的事务B修改过了
另一个准确的说法:是在一个事务内,最开始读到的数据和事务结束前的任意时刻读到的同一批数据出现不一致的情况。
场景讲解
小张媳妇去取款买衣服,9点去ATM机器查询余额是:1000元,这个时候小张发工资了,按时上交,小张也去ATM存现金,小张媳妇也只是查询余额,没有对账户进行存取款,这个时候小张查询余额就是1000元,但是在小张查询完之后,另一边的小张媳妇取了200,余额还剩800,而且这200已经拿到手了(说明取款的事务已经结束了),但是小张再次查询时候发现余额是800而不是1000了,这个时候会有一个疑问:查询两次不都是最新准确的余额嘛?怎么不对嘛?按照平常的逻辑,查询两次,两次不同结果是正确的,但是按照事务的ACID原则,同一个事务中查询两次,两次结果还不一样,就有些问题了,我们结合图解看一下
图解
时间 | 小张存款事务A | 小张媳妇取款事务B |
9:00 | 开始事务 | |
9:05 | 开始事务 | |
9:10 | 查询账户余额是:1000元 | |
9:15 | 查询账户余额:1000元 | |
9:16 | 取出200元,修改余额为800元,现金也拿到手了 | |
9:17 | 事务提交 | |
9:18 | 查询账户余额为800元(不可重复读) |
在数据库访问中,同一个事务范围内两个相同的查询却返回了不同数据,这就是不可重复读
幻读
概念
事务A重新执行一个查询,返回一系列符合查询条件的行,发现其中插入了被事务B提交的行,
场景讲解
小张媳妇去ATM想查一下余额还有多少,第一次查询的时候是1000元,但是这个时候呢,小张去查询余额也是1000元,在这个时候小张媳妇提前取出了所有余额,余额现在是0,紧接着小张也要取1000,但是ATM直接告诉他余额为0,那这个余额,在小张媳妇取完钱之后,小张的第一次查询的结果就属于幻读
图解
时间 | 小张取款事务A | 小张媳妇取款事务B |
9:00 | 开始事务 | |
9:05 | 开始事务 | |
9:10 | 查询账户余额:1000元 | |
9:15 | 取款1000元,余额为0元 | |
9:16 | 事务提交 | |
9:17 | 取款1000元,ATM提示余额不足 (这里面涉及到第二次余额查询,相对比这次查询,上面的第一次查出来的结果就是幻读) |
小张会很诧异,刚才查的还有1000,我这一取咋还余额不足了,然后去柜台一查,哦~原来是被取走了,然后确认了这笔钱是媳妇取走的
第一类丢失更新
概念
事务A撤销操作时,把已经提交的事务B更新的数据给覆盖了
图解
时间 | 小张取款事务A | 小张媳妇转账事务B |
9:00 | 开始事务 | |
9:05 | 开始事务 | |
9:10 | 查询余额为1000元 | |
9:15 | 查询余额为1000元 | |
9:16 | 转账100元,余额为1100元 | |
9:17 | 提交事务 | |
9:18 | 取出100元,余额为900元 | |
9:19 | ATM现金不够,取款无效,撤回100元 | |
9:20 | 余额为1000元 (将转账更新的1100元覆盖了) |
小张媳妇跟小张说:我赚了100块,现在卡里还有1100,我跟你说一声,小张说:胡说,刚才我取款,没取成,专门看了还有1000,其他的也别管了,让他们俩回家打吧,哈哈哈
第二类丢失更新
概念
事务A覆盖事务B已经提交的数据,造成事务B所做的操作丢失
图解
时间 | 小张转账事务A | 小张媳妇取款事务B |
9:00 | 开始事务 | |
9:05 | 开始事务 | |
9:10 | 查询余额为1000元 | |
9:15 | 查询余额为1000元 | |
9:16 | 取款100元,余额为900元 | |
9:17 | 提交事务 | |
9:18 | 汇入账户100元,余额为1100元 | |
9:19 | 提交事务 | |
9:20 | 查询账户余额为1100(把他媳妇真实操作过的余额900元的数据给覆盖了) |
小张事后跟媳妇说我转了100块钱,余额还剩1100,媳妇说:胡扯,我才取的100,明明还有900,跟上面一样,回家让他们俩打吧,哈哈哈