汗颜!工作10年去面试,被“MySQL怎么保证事物一致性”难倒了
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了汗颜!工作10年去面试,被“MySQL怎么保证事物一致性”难倒了相关的知识,希望对你有一定的参考价值。
参考技术A 阿牛去一家中意的公司面试,本以为凭借以往丰富的经验,肯定手到擒来,结果第一个问题,我就“出门右拐”了。问题就是:mysql是怎么保证事务一致性的?
回到家阿牛翻阅资料,终于搞懂了,在这里分享给大家。
定义
在搞清楚问题答案之前,先搞清楚以下几个名词以及大致的用处
redo log:
通常是物理日志,记录的是数据页的物理修改,而不是某一行或某几行修改成怎样怎样,它用来恢复提交后的物理数据页(恢复数据页,且只能恢复到最后一次提交的位置)、Innodb特有的,他在存储引擎层。循环写的,空间固定会用完。作用是crash-safe能力
binlog:
是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ” 是 MySQL 的 Server 层实现的,所有引擎都可以使用。是可以追加写入的,“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。作用是数据归档
undo log:
有两个作用:提供回滚和多个行版本控制(MVCC)。
在数据修改的时候,不仅记录了redo,还记录了相对应的undo,如果因为某些原因导致事务失败或回滚了,可以借助该undo进行回滚。
SQL执行的过程
了解了以上名词之后,让我们看一下“一条更新SQL语句执行的过程是什么?”
如图1有几个关键步骤:
1、先查找记录所在的Innodb页在不在内存里;如果不在内存里则将记录所在的页加载在内存里;根据SQL语句在内存中将记录更新
2、将更新前的记录写入undolog
3、根据记录的更新值将变更写入redolog(buffer)中,并将状态变更为prepare
4、将变更记录到逻辑日志
5、redolog日志中的状态修改为commit,返回结束
至此:一条更新语句的过程结束
上面的步骤中有些同学可能会有一些疑问:为什么更新一条记录要把一整页数据加载到内存里答:因为Innodb引擎中,最小的存储单位是页为什么一定要加载到内存里?答:因为所有的计算操作都是在内存里,操作完成后最终才写回磁盘为什么要写入redolog,直接写入磁盘,然后写入binlog就好了啊?答:这将在下面会提到,请往后看
为了加深理解,准备了下面2张图辅助理解
以图3为例,让我们看看在每个步骤出现异常的时候,到底怎么保证事物一致性的吧!1、步骤123,所有的操作最多还只是内存里,如果出现宕机、断电等异常, 记录不会有任何变动,事物是一致的2、步骤4刚执行完,断电了,因为redolog还处在prepare状态, 这时候事物也是一致的3、步骤5记录binlog的过程中断电了,这时候要保证主从一致性, 事物也是不生效的,最终也是一致的4、步骤6、7如果中间任何一个时刻断电了,这时候情况就不一样了,事物是生效的,因为redolog、binlog的数据都是完整的,服务器重启后可以按照xid来去查看binlog、redolog中是否都存在, 都存在该事物就是生效的。上面就是怎么保证事务一致性的根本原因
为什么要使用redolog?
回答这个问题之前,我们先看看redolog用图形表示的
图4是redolog的形象一点的表现,并不是说redolog 长这个样子,只是为了更形象;一般情况下redolog一组4个文件,每个文件1个G,其中write pos是指redolog当前写到什么位置了,check point是指上次刷脏结束的位置,当write log和check point重合时,所有的进程停止,开始新一轮的刷脏操作。刷完后redolog清空开始下一轮的写入,往返重复。
可能这样表示有点抽象,让我们看下图5
从上图中可以看的更形象一点,在sql执行的时候,会有磁盘IO将数据页加载到内存,然后在内存中将数据修改,修改后的数据页在内存中叫做脏页(叫脏页因为和磁盘中的数据不一致啊),又因为在内存中容易丢失,所以将数据页的变更记录如redolog中,随着记录插入、更新等操作的增多,redolog空间慢慢的满了,这时候就开始刷脏操作了,page cleaner thread线程会将所有的脏页数据刷新到磁盘,使得变更最终被持久化到磁盘。
讲到这里一定还会有人不太理解,刷脏之前断电了咋办?
这就是redolog的另一个重要的作用,crash-safe能力,实现的逻辑是这样的,断电后内存的数据都没了,重启后读取redolog文件,因为redolog文件记录的是在Innodb页x的m处做了y的修改,所以根据redolog将涉及到的Innodb页重新加载到内存,根据redolog的记录将内存中的数据重新修改,这样就能恢复断电前的数据了。
完
下期预告:还是MySQL,敬请期待
本文首发自: 程序员阿牛
2020年去一线大厂面试先过SSM框架源码这一关!
SSM框架介绍
(1)持久层(Mybatis):Dao层(mapper)
DAO层:DAO层主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此。
DAO层的设计首先是设计DAO的接口。
然后在Spring的配置文件中定义此接口的实现类。
然后就可在模块中调用此接口来进行数据业务的处理,而不用关心此接口的具体实现类是哪个类,显得结构非常清晰。
DAO层的数据源配置,以及有关数据库连接的参数都在Spring的配置文件中进行配置。
(2)业务层(Spring):Service层
Service层:Service层主要负责业务模块的逻辑应用设计。
首先设计接口,再设计其实现的类。
接着再在Spring的配置文件中配置其实现的关联。这样我们就可以在应用中调用Service接口来进行业务处理。
Service层的业务实现,具体要调用到已定义的DAO层的接口。
封装Service层的业务逻辑有利于通用的业务逻辑的独立性和重复利用性,程序显得非常简洁。
(3)表现层(springMVC):Controller层(Handler层)
Controller层:Controller层负责具体的业务模块流程的控制。
在此层里面要调用Service层的接口来控制业务流程。
控制的配置也同样是在Spring的配置文件里面进行,针对具体的业务流程,会有不同的控制器,我们具体的设计过程中可以将流程进行抽象归纳,设计出可以重复利用的子单元流程模块,这样不仅使程序结构变得清晰,也大大减少了代码量。
(4)视图层:View层
View层:View层与控制层结合比较紧密,需要二者结合起来协同工发。View层主要负责前台jsp页面的表示。
关于框架源码的大体知识总结了一个思维导图分享给大家
SSM框架面试题
1、如何理解Spring?
2、介绍一下Spring的事物管理
3 、SSM优缺点、使用场景?
4、MyBatis 中使用#和$书写占位符有什么区别?
5、解释一下 MyBatis 中命名空间(namespace)的作用。
6、什么是 IoC 和 DI?DI 是如何实现的?
7、解释一下什么叫 AOP(面向切面编程)?
8、你是如何理解"横切关注"这个概念的?
9、你如何理解 AOP 中的连接点(Joinpoint)、切点(Pointcut)、增强(Advice)、引介(Introduction)、织入(Weaving)、切面(Aspect)这些概念?
10、Spring 支持的事务管理类型有哪些?你在项目中使用哪种方式?
11、Spring MVC的工作原理是怎样的?
12、什么是 XSS 攻击?
13、SQL 注入攻击?
14、什么是CSRF攻击?
15、简述Mybatis一级、二级缓存
16、JDBC编程有哪些不足之处,MyBatis是如何解决这些问题的?
SSM框架面试题解析
1、如何理解Spring?
具体来说Spring是一个轻量级的容器,用于管理业务相关对象的。核心功能主要为:IOC,AOP,MVC。
IOC:控制反转,将对象的创建过程交给容器,让容器管理对象的生命周期如创建,初始化,销毁等。
AOP:面向切面编程,对关注点进行模块化,通过对某一功能点进行编程,比如记录日志,有很多个类都需要记录日志的方法,则创建记录日志的代理方法,需要调用该功能是只需要调用代理方法,这就是AOP。
MVC:SpringMvc,Spring提供的基于MVC模式设计的Web框架,如今比较流行的框架之一。
2、介绍一下Spring的事物管理
事务就是对一系列的数据库操作(比如插入多条数据)进行统一的提交或回滚操作,如果插入成功,那么一起成功,如果中间有一条出现异常,那么回滚之前的所有操作。这样可以防止出现脏数据,防止数据库数据出现问题。
开发中为了避免这种情况一般都会进行事务管理。Spring中也有自己的事务管理机制,一般是使用TransactionMananger进行管 理,可以通过Spring的注入来完成此功能。
Spring支持如下两种方式的事务管理:
编程式事务管理:这意味着你可以通过编程的方式管理事务,这种方式带来了很大的灵活性,但很难维护。
声明式事务管理:这种方式意味着你可以将事务管理和业务代码分离。你只需要通过注解或者XML配置管理事务。
一般选择声明式事务管理,因为这种方式和应用程序的关联较少。
3 、SSM优缺点、使用场景?
(1)Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句,不过mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。
(2)Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。
(3)Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。
(4)总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。
4、MyBatis 中使用#和$书写占位符有什么区别?
答:#将传入的数据都当成一个字符串,会对传入的数据自动加上引号;$将传入的数据直接显示生成在SQL 中。
注意:使用$占位符可能会导致 SQL 注射攻击,能用#的地方就不要使用$,写 order by 子句的时候应该用$而不是#。
5、解释一下 MyBatis 中命名空间(namespace)的作用。
答:在大型项目中,可能存在大量的 SQL 语句,这时候为每个 SQL 语句起一个唯一的标识(ID)就变得并不容易了。为了解决这个问题,在 MyBatis 中,可以为每个映射文件起一个唯一的命名空间,这样定义在这个映射文件中的每个 SQL 语句就成了定义在这个命名空间中的一个 ID。只要我们能够保证每个命名空间中这个 ID 是唯一的,即使在不同映射文件中的语句 ID 相同,也不会再产生冲突了。
6、什么是 IoC 和 DI?DI 是如何实现的?
答:IoC 叫控制反转,是 Inversion of Control 的缩写,DI(Dependency Injection)叫依赖注入,是对 IoC 更简单的诠释。控制反转是把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的"控制反转"就是对组件对象控制权的转移,从程序代码本身转移到了外部容器,由容器来创建对象并管理对象之间的依赖关系。IoC 体现了好莱坞原则 -"Don’tcallme,we willcallyou"。依赖注入的基本原则是应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由容器负责,查找资源的逻辑应该从应用组件的代码中抽取出来,交给容器来完成。DI 是对 IoC 更准确的描述,即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。
7、解释一下什么叫 AOP(面向切面编程)?
答:AOP(Aspect-Oriented Programming)指一种程序设计范型,该范型以一种称为切面(aspect)的语言构造为基础,切面是一种新的模块化机制,用来描述分散在对象、类或方法中的横切关注点(crosscutting concern)。
8、你是如何理解"横切关注"这个概念的?
答:"横切关注"是会影响到整个应用程序的关注功能,它跟正常的业务逻辑是正交的,没有必然的联系,但是几乎所有的业务逻辑都会涉及到这些关注功能。通常,事务、日志、安全性等关注就是应用中的横切关注功能。
9、你如何理解 AOP 中的连接点(Joinpoint)、切点(Pointcut)、增强(Advice)、引介(Introduction)、织入(Weaving)、切面(Aspect)这些概念?
答:a. 连接点(Joinpoint):程序执行的某个特定位置(如:某个方法调用前、调用后,方法抛出异常后)。一个类或一段程序代码拥有一些具有边界性质的特定点,这些代码中的特定点就是连接点。Spring 仅支持方法的连接点。
b. 切点(Pointcut):如果连接点相当于数据中的记录,那么切点相当于查询条件,一个切点可以匹配多个连接点。Spring AOP 的规则解析引擎负责解析切点所设定的查询条件,找到对应的连接点。
c. 增强(Advice):增强是织入到目标类连接点上的一段程序代码。Spring 提供的增强接口都是带方位名的,如:BeforeAdvice、AfterReturningAdvice、ThrowsAdvice 等。很多资料上将增强译为“通知”,这明显是个词不达意的翻译,让很多程序员困惑了许久。
说明: Advice 在国内的很多书面资料中都被翻译成"通知",但是很显然这个翻译无法表达其本质,有少量的读物上将这个词翻译为"增强",这个翻译是对 Advice 较为准确的诠释,我们通过 AOP 将横切关注功能加到原有的业务逻辑上,这就是对原有业务逻辑的一种增强,这种增强可以是前置增强、后置增 强、返回后增强、抛异常时增强和包围型增强。
d. 引介(Introduction):引介是一种特殊的增强,它为类添加一些属性和方法。这样,即使一个业务类原本没有实现某个接口,通过引介功能,可以动态的未该业务类添加接口的实现逻辑,让业务类成为 这个接口的实现类。
e. 织入(Weaving):织入是将增强添加到目标类具体连接点上的过程,AOP 有三种织入方式:
①编译期织入:需要特殊的 Java 编译期(例如 AspectJ 的 ajc);
②装载期织入:要求使用特殊的类加载器, 在装载类的时候对类进行增强;
③运行时织入:在运行时为目标类生成代理实现增强。Spring 采用了动 态代理的方式实现了运行时织入,而 AspectJ 采用了编译期织入和装载期织入的方式。
f. 切面(Aspect):切面是由切点和增强(引介)组成的,它包括了对横切关注功能的定义,也包括了对连接点的定义。
10、Spring 支持的事务管理类型有哪些?你在项目中使用哪种方式?
答:Spring 支持编程式事务管理和声明式事务管理。许多 Spring 框架的用户选择声明式事务管理,因为这种方式和应用程序的关联较少,因此更加符合轻量级容器的概念。声明式事务管理要优于编程式事务管理,尽管在灵活性方面它弱于编程式事务管理,因为编程式事务允许你通过代码控制业务。
11、Spring MVC的工作原理是怎样的?
答:SpringMVC工作原理图如下:
(1)客户端的所有请求都交给前端控制器 DispatcherServlet 来处理,它会负责调用系统的其他模块来真正处理用户的请求。
(2) DispatcherServlet 收到请求后,将根据请求的信息(包括 URL、HTTP 协议方法、请求头、请求参数、Cookie 等)以及 HandlerMapping 的配置找到处理该请求的 Handler(任何一个对象都可以作为请求的 Handler)。
(3)在这个地方 Spring 会通过 HandlerAdapter 对该处理器进行封装。
(4)HandlerAdapter 是一个适配器,它用统一的接口对各种 Handler 中的方法进行调用。
(5)Handler 完成对用户请求的处理后,会返回一个 ModelAndView 对象给 DispatcherServlet,ModelAndView 顾名思义,包含了数据模型以及相应的视图的信息。
(6) ModelAndView 的视图是逻辑视图,DispatcherServlet 还要借助 ViewResolver 完成从逻辑视图到真实视图对象的解析工作。
(7)当得到真正的视图对象后,DispatcherServlet 会利用视图对象对模型数据进行渲染。
(8)客户端得到响应,可能是一个普通的 HTML 页面,也可以是 XML 或 JSON 字符串,还可以是一张图片或者一个 PDF 文件。
12、什么是 XSS 攻击?
答: XSS(Cross Site Script,跨站脚本攻击)是向网页中注入恶意脚本在用户浏览网页时在用户浏览器中执行恶意脚本的攻击方式。跨站脚本攻击分有两种形式:反射型攻击(诱使用户点击一个嵌入恶意 脚本的链接以达到攻击的目标,目前有很多攻击者利用论坛、微博发布含有恶意脚本的 URL 就属于这种方式)和持久型攻击(将恶意脚本提交到被攻击网站的数据库中,用户浏览网页时,恶意脚本从数据 库中被加载到页面执行,QQ 邮箱的早期版本就曾经被利用作为持久型跨站脚本攻击的平台)。XSS 虽然不是什么新鲜玩意,但是攻击的手法却不断翻新,防范 XSS 主要有两方面:消毒(对危险字符进行转义)和HttpOnly (防范 XSS 攻击者窃取 Cookie 数据)。
13、SQL 注入攻击?
答: SQL 注入攻击是注入攻击最常见的形式(此外还有 OS 注入攻击(Struts 2 的高危漏洞就是通过OGNL 实施 OS 注入攻击导致的)),当服务器使用请求参数构造 SQL 语句时,恶意的 SQL 被嵌入到SQL 中交给数据库执行。SQL 注入攻击需要攻击者对数据库结构有所了解才能进行,攻击者想要获得表结构有多种方式:
(1)如果使用开源系统搭建网站,数据库结构也是公开的(目前有很多现成的系统可以直接搭建论坛,电商网站,虽然方便快 捷但是风险是必须要认真评估的);
(2)错误回显(如果将服务器的错误信息直接显示在页面上,攻击者可以通过非法参数引发页面错误从而通过错误信息了解数据库结构,Web应用应当设置友好的错误页,一方面符合最小惊讶原则,一方面屏蔽掉可能给系统带来危险的错误回显信息);
(3)盲注。防范 SQL 注入攻击也可以采用消毒的方式,通过正则表达式对请求参数进行验证,此外,参数绑定也是很好的手段,这样恶意的 SQL 会被当做 SQL 的参数而不是命令被执行,JDBC 中的 PreparedStatement 就是支持参数绑定的语句对象,从性能和安全性上都明显优于 Statement。
14、什么是CSRF攻击?
答: CSRF 攻击(Cross Site Request Forgery,跨站请求伪造)是攻击者通过跨站请求,以合法的用户身份进行非法操作(如转账或发帖等)。CSRF 的原理是利用浏览器的 Cookie 或服务器的Session,盗取用户身份,其原理如下图所示。防范 CSRF 的主要手段是识别请求者的身份,主要有以下几种方式:
(1) 在表单中添加令牌(token);
(2) 验证码;
(3) 检查请求头中的 Referer。
令牌和验证都具有一次消费性的特征,因此在原理上一致的,但是验证码是一种糟糕的用户体验,不是必要的情况下不要轻易使用验证码,目前很多网站的做法是如果在短时间内多次提交一个表单未获得成功后才要求提供验证码,这样会获得较好的用户体验。
15简述Mybatis一级、二级缓存
1)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空。
2)二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。要开启二级缓存,你需要在你的 SQL 映射文件中添加一行:
3)对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。
16、JDBC编程有哪些不足之处,MyBatis是如何解决这些问题的?
(1)数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
解决:在SqlMapConfig.xml中配置数据链接池,使用连接池管理数据库链接。
(2) Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。
(3) 向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
解决: Mybatis自动将java对象映射至sql语句。
(4)对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
解决:Mybatis自动将sql执行结果映射至java对象。
另外的参考回答
频繁的创建数据连接,关闭资源,造成性能的下降,使用数据文库连接池 解决这个问题用数据库连接池.在SqlMapConfig.xml 配置数据库连接池 c3p0 DBCP
Jdbc 编程sql 的可维护性不高. Mybatis采用配置文件的方式解决sql可维护的问题
在mapper.xml中配置 ,是sql与代码分离 可维护行变高
Jdbc 传入参数比较麻烦. 参数有时候多,参数要和占位符一一对应.
Mybatis 使用statement 的 paremterType 定义输入的参数类型
对结果解析比较麻烦. Mybatis 使用resultType 自动映射到pojo中解决了jdbc解析结果的麻烦
欢迎大家关注我的公种浩【程序员追风】,2019年多家公司java面试题整理了120多页pdf文档,文章都会在里面更新,整理的资料也会放在里面。
最后
欢迎大家一起交流,喜欢文章记得关注我点个赞哟,感谢支持!
以上是关于汗颜!工作10年去面试,被“MySQL怎么保证事物一致性”难倒了的主要内容,如果未能解决你的问题,请参考以下文章
Java集合详解10:ConcurrentHashmap面试题汇总,最近找工作老是被问!
8年程序员面试架构师被淘汰,HR:没10年前端经验,别来应聘