[肥朝]从一次问题排查聊聊问什么要懂原理

前言

上周五,一同事在开发时遇到了一个问题,叫我帮忙看下.在描述这个同事遇到问题以前,我先简单作一些知识的铺垫,不然很差描述.这里面涉及到的知识点有Spring的事务传播机制数据库的隔离级别等.面试

本篇重点是解决同事遇到的问题,由于这两个知识点都先简单谈谈,只为引出主题.后面这两个会专门用一篇来说sql

Spring的事务传播机制

Sring的事务传播机制有七种,本文涉及到的有两种数据库

REQUIRED : 用得最多(估计高达90%),也是默认的模式.若当前没有事务,则新建事务,若当前已存在一个事务, 则加入到该事务中缓存

REQUIRES_NEW : 新建一个事务bash

Spring的事务传播机制.后面我会用一篇文章专门来说,给你们列各类典型的题型,按照高中的题型训练模式,完全弄懂Spring的传播机制,即便在各类复杂嵌套 + try场景下也能云淡风轻地肯定回滚状况.包括解析以前很是经典的一道面试题mybatis

  • 作51次操做,前面50次成功,第51次失败,所有回滚
  • 作51次操做,前面50次成功,第51次失败,只回滚第51次,全面50次照常提交

事务的隔离级别

考虑到部分同窗英文问题,我特地标记了中文性能

1.Read Uncommitted: 读未提交spa

这个基本不可能用,从字面意思你就知道了,读到别人还未提交的数据,别人都没提交,你怎么知作别人接下来是要提交仍是回滚?既然不知道你就读,天然会有问题.这个问题就是咱们说的脏读.debug

2.Serializable: 串行化3d

其实就是同步化,性能太差,基本不可能用这个.可是这个是惟一能解决幻读问题的.

画图分析

剩下两种隔离级别

  • Read Committed: 读已提交

  • Read Repeatable: 可重复读

就比较重要了,咱们画图来分析

好比我问,当t4时,查询出来的数据,name是大肥朝仍是toby.其实你心里就不是很肯定了,可是我若是把提交事务这几个字加粗标红,而后引诱一下,绝大多数同窗根本把持不住!!!

既然都提交事务了,那读出来的天然是toby啦.

其实t4读出来是toby仍是大肥朝这个取决与你用的是读已提交可重复读.其实你从这个中文名称均可以猜到了,若是是读已提交,那么查出来的就是toby.若是是可重复读.读出来的天然就是大肥朝. MySQL默认用的是可重复读.Oracle默认用的是读已提交.

舒适提示: 这个后面也能够考虑再写一篇详细讲一下这个隔离级别,由于通常问到可重复读,有深度的面试官会继续追问,可重复读是如何实现的?具体怎么实现的咱们能够先关注肥朝公众号,后面再具体说数据库的MVCC机制

问题描述

因为业务具备必定的复杂度,不利于你们观看,所以我这里特地抽象简化了模型.

首先,我先把数据库的隔离级别改为读已提交.截图为证:

那么问题来了,请问步骤3查询出来的数据是什么呢.咱们一块儿来见证

见证答案

1.查询完数据,准备更新数据

2.更新完成提交了事务,咱们看得出此时数据库已经改为了toby

3.震惊!查出来的数据居然是大肥朝

这个时候彷佛就不厚道了,肥朝你前面怎么说的,你前面说读已提交读出来的是别人已经提交的,那么应该是toby才对啊,怎么仍是大肥朝?.

开始排查

咱们把配置文件设置成`debug级别一切就豁然开朗了

logging.level.com.toby.demo.dao=debug
logging.level.org.mybatis=debug
复制代码

这里我特地用不一样颜色给你们标记清楚了,其实看到只输出两次SQL日志你们就知道了.第三次查询没有输出SQL,这很明显是用到了Mybatis的缓存了.再根据我标记的SqlSession信息来看,这里就是用到了Mybatis一级缓存

解决办法

解决办法有不少,咱们知道Mybatis一级缓存的做用域是SqlSession,那么只要两次查询是不一样的SqlSession那天然这个一级缓存就失效了.一级缓存失效了.就会查询两次,输出两次sql.这个时候是toby仍是大肥朝就真的取决于我前面说的隔离级别了.好比一个简单的改法是

改法有不少,具体根据那么的业务来就能够了,固然也能够采用上面那种

写在最后

肥朝 是一个专一于 原理、源码、开发技巧的技术公众号,号内原创专题式源码解析、真实场景源码原理实战(重点)。扫描下面二维码关注肥朝,让本该造火箭的你,再也不拧螺丝!

相关文章
相关标签/搜索