又整理了一些面试遇到的问题,有一些待继续解决
sql语句的效率较低,如何排查(explain工具)
慢查询:在MySQL中响应时间超过阀值的语句,具体指运行时间超过long_query_time值的SQL。会被记录到MySQL的慢查询日志
可以通过 slow_query_log 标志位置 true,将慢查询日志的记录动作开启
得到执行较慢的sql语句列表后,使用 explain 工具进行分析:
explain 待分析的SQL语句
会得到如下的一个执行结果:
在其中,会展示本条sql语句执行过程的相关信息,比较需要关注的如:
· key:表示 sql 语句命中的索引,如图 key = PRIMARY 表示命中了主键索引;若为NULL,则表示没有命中索引,使用了全表扫描;
· rows:表示执行过程扫描的条目数量,一定程度上可以反应执行时间,扫描条目对于执行时间的影响很大
(虽然创建索引对于查找可以有帮助,但并非所有命中了索引的查找都会很快,所以也需要关注 rows 参数反应的扫描条目数量)
InnoDB 上限 64TB 是为什么
InnoDB 的页号是一个 32bit 的 int 类型,一个页的大小是 16kb
所以总大小:2^32 * 16kb = 2^2*16 * 2^30kb = 64TB
是否看过MySQL中的锁机制的底层源码
性能划分:乐观锁、悲观锁
乐观锁:如 CAS
悲观锁:必须加锁,开销较大,如:for update
操作类型划分:读锁(共享锁)、写锁(排他锁)
读锁(共享锁):针对同一条目,读操作可以同时进行,但任何事务都不能进行
写锁(排他锁):获取排他锁的事务可进行读写操作。获取到写锁的事务未完成之前,会阻塞其他事务获取写锁或读锁。
粒度划分:行锁、页锁、表锁
行锁
定义:只对当前正在操作的条目进行加锁
方法:共享锁和排他锁
特点:大大减少数据库操作冲突;加锁粒度最小,开销大;有可能会出现死锁的情况,出现死锁的解决办法就是必须有一方事务回滚或者同时回滚;
页锁
定义:行锁和表锁的一种折衷做法,对当前正在操作条目相邻的一段数据进行加锁
特点:数据库操作冲突不至于过多,加锁开销也不至于过大
表锁
定义:表示当前的操作对整张表加锁
方法:元数据锁(Metadata Lock,MDL)、表锁
特点:发生锁冲突的概率很大;资源开销较少;不会出现死锁的情况
元数据锁:一种读写锁,读操作不互斥,读写、写操作之间互斥,写锁优先级 > 读锁优先级,事务结束才会释放
Bean生命周期
核心生命周期:实例化 —— 属性赋值 —— 初始化 —— 销毁
可以理解为如下:
1、BeanDefinition 的解析,注册,合并
2、Bean 实例化,此时还没有调用构造函数生成对象
3、Bean 属性赋值,查找 @Autowired 和 @Value 标注的方法或属性,进行依赖注入
4、Bean 初始化,已经生成 bean,进行属性赋值
5、Bean销毁,此时并不会触发 gc
AOP的理解
即面向切面编程,作为面向对象的一种补充,将与业务无关的公共行为和逻辑进行抽取和封装,作为一个可重用的模块,该模块即“切面”
经典实现:AspectJ
场景:日志记录,性能统计,安全控制,事务处理,异常处理等
作用:减少重复代码,降低模块间的耦合度,提高可维护性。
【待补充】
拦截器与过滤器的区别、使用
原理:
过滤器:基于回调函数;
拦截器:基于 Java 反射机制(动态代理)。
使用范围:
过滤器:Servlet 规范,需要实现 javax.servlet.Filter 接口,由 Servlet 容器管理,依赖 Tomcat 等容器;
拦截器:Spring 组件,定义在 org.springframework.web.servlet 包下,由 Spring 容器管理,所以有更加丰富的生命周期处理方法,细粒度,且能够使用 Spring 中的资源,不依赖 Tomcat 等容器。
触发时机:
过滤器:Tomcat 容器与 Servlet 之间触发;
拦截器:Servlet 与 Controller 之间触发。
执行顺序:
过滤前——拦截前——action执行——拦截后——过滤后
桶排序
应用场景:
数据量大、整体数值范围已知、分布较均匀
以大量学生的成绩(0~100)排序为例。
排序算法:
设定桶的数量,一般按均匀划分,如将成绩划分为10个桶,分别存放的成绩区间为:0-10、11-20、…、91-100;
排序时,将当前成绩划分到所属的桶,将属于一个桶的数值用链表存储;
当有新的数值来到该桶,使用插入排序维护链表的排序关系;
最后将每个桶的数据按链表顺序取出,即可得到整体的排序结果。
特点:
感觉桶排序类似于插入排序,区别在于先将待排数据划分为小的数据集,再分别进行插入排序。是一种空间换时间,来降低时间复杂度的感觉
时间复杂度最好可以接近 O(N)
空间复杂度差不多在 O(N)
算法比较稳定
Full GC 什么情况触发
1、老年区空间不足;
2、Young GC的时候,若之前每次晋升到老年代的平均大小 > 老年代的剩余空间,会触发;
3、System.gc();
4、分配大对象,会直接进入老年区,若空间不足会触发
…
是否看过concurrent类底层代码、是否看过Java锁机制的底层代码
和锁的种类与底层实现有关,了解不多,只回答了这些
CAS 自旋,未竞争到则让出 CPU 时间片
synchronized 加锁,底层实现未知
【其余待补充】
大树递归会出现的问题
栈溢出
解决方法上,考虑进行更换,更换决策如:LRU、FIFO等
线程安全
在多线程执行计算机程序的时候,需要同步机制保证各个线程能够正确执行自己的逻辑,不会出现线程安全问题。
同步机制,即保证操作的原子性,可以利用锁机制、系统自带的原子操作、机器指令,如CAS。锁、synchronized 需要操作系统进行裁决,开销较大;CAS 原子操作在 CPU 级进行裁决,开销更小。
synchronized修饰不同类型:
非静态同步方法:锁住的是当前实例;
静态同步方法:锁住的是该类的Class对象;
静态代码块:锁住的是synchronized关键字后面括号内的对象。