面试题整理(三)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 面试题整理(三)

五、Java虚拟机面试题


a2d5ed498525278d2fc021f99baf9941.png

1、什么是Java虚拟机?为何被称作“平台无关的编程语言”?

Java虚拟机是一个可以执行Java字节码(.class)的虚拟机进程。


Java源文件(.java)被编译成Java字节码(.class)。允许应用程序可以在任意平台。


因为Java虚拟机知道底层硬件平台的指令长度和其他特性。


2、Java的内存结构

(1)Java堆:虚拟机启动时创建,存放对象实例(new)。各线程共享。


(2)方法区:存储加载的类的信息、常量、静态变量、编译后的代码等。各线程共享。


(3)程序计数器:当前线程所执行的字节码的行号指示器。线程私有。


(4)JVM栈:描述Java方法执行的内存模型,每个栈帧对应一个方法,线程私有。


(5)本地方法栈:为虚拟机使用到的Native方法服务。

b96a90a44f40c8ea1bed0755a590126a.png

41b07300ef8603c2f89e4dcd12229405.png

Java虚拟机会出现的两种错误 :


StackOverFlowError: 若Java虚拟机栈的内存大小不允许动态扩展,那么当线程请求栈的深度超过当前Java虚拟机栈的最大深度的时候,就抛出StackOverFlowError 错误。

OutOfMemoryError:若Java虚拟机栈的内存大小允许动态扩展,且当线程请求栈时内存用完了,无法再动态扩展了,此时抛出 OutOfMemoryError错误。

扩展:那么方法/函数如何调用?


Java 栈可用类比数据结构中栈,Java 栈中保存的主要内容是栈帧,


每一次函数调用都会有一个对应的栈帧被压入 Java 栈,


每一个函数调用结束后,都会有一个栈帧被弹出。Java 方法有两种返回方式:


return 语句。

抛出异常。

不管哪种返回方式都会导致栈帧被弹出。

3、内存分配

(1)寄存器:无法控制。


(2)静态域:static定义的成员。


(3)常量池:编译时被确定并保存到.class文件中的(final)常量值和一些文本修饰的符号引用。


(4)非RAM存储:硬盘等永久存储空间。


(5)堆内存:new创建的对象和数组,由Java虚拟机自动垃圾回收器管理,存取速度慢。


栈内存:基本类型的变量和对象的引用变量(对内存空间的访问地址),速度快,可以共享,但是大小与生存周期必须确定,缺乏灵活性。


4、类加载器

(1)启动类加载器:负责加载JDK\jre\lib下的文件。


(2)扩展类加载器:负责加载JDK\jre\lib\ext目录中的所有类库。


(3)应用程序类加载器:负责加载用户类路径所指定的类。


5、JVM如何加载class文件?

类加载器:运行时查找和装入类文件中的类。


加载:把类的.class文件中的数据读入到内存之中(通过创建字节数组读入.class文件),然后产生与所加载类对应的Class对象。


连接:验证、准备(为静态变量分配内存并设置默认的初始值)和解析。


初始化:(1)如果类存在直接的父类,且这个父类还没有被初始化,则先初始化父类。


(2)如果类中存在初始化语句,就依次执行这些初始化语句。


6、Java对象创建的过程

(1)拿到内存创建的指令(new 类名),来到方法区,根据new的参数,在常量池找到一个类的符号引用。


(2)检查符号引用,检查是否被加载、解析和初始化过。


(3)分配内存。


(4)初始化:抽象数据类型默认初始化为null,基本数据类型为0,布尔为false…


(5)调用对象的初始化方法。

fff1897028b54737d1edd5c5dcd55b07.png



7、Java对象的结构

(1)对象头:运行时数据、指针类型。


(2)实例数据:存储对象真正的有效信息。


(3)对齐填充:要求对象初始地址必须是8字节的整数倍。


8、类的生命周期

加载:根据查找路径找到相应的 class 文件然后导入;

验证:检查加载的 class 文件的正确性;

准备:给类中的静态变量分配内存空间;

解析:虚拟机将常量池中的符号引用替换成直接引用的过程。符号引用就理解为一个标示,而在直接引用直接指向内存中的地址;

初始化:对静态变量和静态代码块执行初始化工作。

9、什么情况下会发生栈溢出?

栈的大小可以通过-Xss参数设置,当递归层次太深的时候就会发生栈溢出。(例循环、递归)。


10、Java垃圾回收机制,GC是什么?为什么要GC?

Java垃圾回收机制:低优先级,只有在JVM空闲和当前堆内存不足时,会执行。扫描出那些没有被引用过的类,将他们添加到要回收的集合中,进行回收。


GC 是垃圾收集的意思。


Java 提供的 GC 功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的。


11、JVM新生代、老年代、持久代都存储些哪些东西?

(1)新生代:new出的对象。


(2)老年代:新生代中经历了N次垃圾回收仍存活的对象、大对象直接存入、Survivor空间不足。


(3)持久代:指方法区。


12、Java会存在内存泄漏吗?

内存泄漏:指一个不再被程序使用的对象或变量一直被占据在内存中。


情况:长生命周期的对象只有断声明周期对象的引用时,可能发生内存泄漏。对生命周期对象已经不需要,但是因为长生命周期对象对其的引用,而无法回收。


13、JVM调优有哪些?

(1)设定堆内存大小。-Mmx:堆内存最大限制。


(2)设定新生代大小:(不能太小,否则会大量涌入老年代)


-XX:NewSize:新生代大小


-XX:NewRatio:新生代和老生代占比


-XX:SurvivorRatio:伊甸园空间和幸存者空间占比


(3)设定垃圾回收器:年轻代:-XX:+UseParNewGC


老年代:-XX:+UseConcMarkSweepGC


说一下 JVM 调优的工具?

JDK 自带了很多监控工具,都位于 JDK 的 bin 目录下,其中最常用的是 jconsole 和 jvisualvm 这两款视图监控工具。


jconsole:用于对 JVM 中的内存、线程和类等进行监控;

jvisualvm:JDK 自带的全能分析工具,可以分析:内存快照、线程快照、程序死锁、监控内存的变化、gc 变化等。

14、如何判断对象可以被回收?

引用计数法

在JDK1.2之前,使用的是引用计数器算法。在对象中添加一个引用计数器,当有地方引用这个对象的时候,引用计数器的值就+1,当引用失效的时候,计数器的值就-1,当引用计数器被减为零的时候,标志着这个对象已经没有引用了,可以回收了

可达性分析法

通过一系列的称为 GC Roots 的对象作为起点, 然后向下搜索; 搜索所走过的路径称为引用链/Reference Chain, 当一个对象到 GC Roots 没有任何引用链相连时, 即该对象不可达, 也就说明此对象是不可用的。

15、 JVM的永久代中会发生垃圾回收么?

垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收(Full GC)。


注:Java 8 中已经移除了永久代,新加了一个叫做元数据区的native 内存区。


16、栈帧有哪些数据?

每个线程栈里的元素就是“栈帧”。


局部变量表、操作数栈、动态连接、返回地址。


17、Java的双亲委托机制是什么?

每一个类都有一个对应它的类加载器。系统中的 ClassLoder 在协同工作的时候会默认使用 双亲委派模型 。即在类加载的时候,系统会首先判断当前类是否被加载过。已经被加载的类会直接返回,否则才会尝试加载。加载的时候,首先会把该请求委派该父类加载器的 loadClass() 处理,因此所有的请求最终都应该传送到顶层的启动类加载器 BootstrapClassLoader 中。当父类加载器无法处理时,才由自己来处理。当父类加载器为null时,会使用启动类加载器 BootstrapClassLoader 作为父类加载器。


18、说一下堆栈的区别?

image.png

19、队列和栈是什么?有什么区别?

队列和栈都是被用来预存储数据的。

image.png

20、为对象分配内存

指针碰撞:如果Java堆的内存是规整,即所有用过的内存放在一边,而空闲的的放在另一边。分配内存时将位于中间的指针指示器向空闲的内存移动一段与对象大小相等的距离,这样便完成分配内存工作。

空闲列表:如果Java堆的内存不是规整的,则需要由虚拟机维护一个列表来记录那些内存是可用的,这样在分配的时候可以从列表中查询到足够大的内存分配给对象,并在分配后更新列表记录。

113aecf63ad182fbbf0ee8ac09d8188d.png

21、处理并发安全问题

对分配内存空间的动作进行同步处理(采用 CAS + 失败重试来保障更新操作的原子性);

把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在 Java 堆中预先分配一小块内存,称为本地线程分配缓冲(Thread Local Allocation Buffer, TLAB)。哪个线程要分配内存,就在哪个线程的 TLAB 上分配。只有 TLAB 用完并分配新的 TLAB 时,才需要同步锁。通过-XX:+/-UserTLAB参数来设定虚拟机是否使用TLAB。

ef6c7d97398a74896ca6e1056fd97192.png


22、说一下 JVM 有哪些垃圾回收算法?

标记-清除算法:标记无用对象,然后进行清除回收。缺点:效率不高,无法清除垃圾碎片。

image.png


复制算法:按照容量划分二个大小相等的内存区域,当一块用完的时候将活着的对象复制到另一块上,然后再把已使用的内存空间一次清理掉。缺点:内存使用率不高,只有原来的一半。 适用于新生代。

image.png

标记-整理算法:标记无用对象,让所有存活的对象都向一端移动,然后直接清除掉端边界以外的内存。适用于老年代。

image.png


分代算法:根据对象的存活周期将内存划分为几块。一般包括年轻代、老年代 和 永久代,新生代基本采用复制算法,老年代采用标记整理算法。


23、分代概念

新生成的对象首先放到年轻代Eden区,当Eden空间满了,触发Minor GC,存活下来的对象移动到Survivor0区,Survivor0区满后触发执行Minor GC,Survivor0区存活对象移动到Suvivor1区,这样保证了一段时间内总有一个survivor区为空。经过多次Minor GC仍然存活的对象移动到老年代。

老年代存储长期存活的对象,占满时会触发Major GC=Full GC,GC期间会停止所有线程等待GC完成,所以对响应要求高的应用尽量减少发生Major GC,避免响应超时。

Minor GC : 清理年轻代

Major GC : 清理老年代

Full GC : 清理整个堆空间,包括年轻代和永久代

所有GC都会停止应用所有线程。


24、为什么分代?

将对象根据存活概率进行分类,对存活时间长的对象,放到固定区,从而减少扫描垃圾时间及GC频率。针对分类进行不同的垃圾回收算法,对算法扬长避短。

25、JVM堆内存常用参数

image.png


26、类加载的过程

JVM的类加载分为5个阶段:加载、验证、准备、解析、初始化。在类初始化完成后就可以使用该类的信息,在一个类不再被需要时可以从JVM中卸载


加载


指JVM读取Class文件,并且根据Class文件描述创建java. lang. Class对象的过程。类加载过程主要包含将Class文件读取到运行时区域的方法区内,在堆中创建java.lang.Class 对象,并封装类在方法区的数据结构的过程,在i卖取Class文件时既可以通过文件的形式读取,也可以通过jar包、war包读取,还可以通过代理自动生成Class或其他方式读取。

验证


主要用于确保Class文件符合当前虚拟机的要求,保障虚拟机自身的安全,只有通过验证的Class文件才能被JVM加载。

准备


主要工作是在方法区中为类变量分配内存空间并设置类中变量的初始值。初始值指不同数据类型的默认值,这里需要注意final类型的变量和非final类型的变量在准备阶段的数据初始化过程不同。

解析


JVM会将常量池中的符号引用替换为直接引用。

初始化


要通过执行类构造器的<client>方法为类进行初始化。<client>方法是在编译阶段由编译器自动收集类中静态语句块和变量的赋值操作组成的。JVM规定,只有在父类的<client>方法都执行成功后,子类中的<client>方法才可以被执行。在一个类中既没有静态变量赋值操作也没有静态语句块时,编译器不会为该类生成<client>方法

27、Java中的4种引用类型

强引用:在Java中最常见的就是强引用。在把一个对象赋给一个引用变量时,这个引用变量就是一个强引用。有强引用的对象一定为可达性状态,所以不会被垃圾回收机制回收。因此,强引用是造成Java内存泄漏(Memory Link )的主要原因。

软引用:软引用通过SoftReference类实现。如果一个对象只有软引用,则在系统内存空间不足时该对象将被回收。

弱引用:弱引用通过WeakReference类实现,如果一个对象只有弱引用,则在垃圾回收过程中一定会被回收。

虚引用:虚引用通过PhantomReference类实现,虚引用和引用队列联合使用,主要用于跟踪对象的垃圾回收状态。

六、MySQL面试题

1、什么是MySQL

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。在Java企业级开发中非常常用,因为 MySQL 是开源免费的,并且方便扩展。


2、数据库三大范式

第一范式:每个列都不可以再拆分。

第二范式:在第一范式的基础上,非主键列完全依赖于主键,而不能是依赖于主键的一部分。

第三范式:在第二范式的基础上,非主键列只依赖于主键,不依赖于其他非主键。

在设计数据库结构的时候,要尽量遵守三范式,如果不遵守,必须有足够的理由。比如性能。事实上我们经常会为了性能而妥协数据库的设计。


3、对慢查询怎么样优化过?

(1)分析语句,看是否查询了多余的行并且抛弃掉了,是否加载了许多结果中不需要的列,对语句进行分析以及重写;


(2)分析语句的执行计划,获得其使用索引的情况,进行修改,使语句可以尽可能的命中索引;


(3)考虑数据量是否太大,可以考虑进行横向或者纵向分表。


4、mysql有关权限的表都有哪几个

MySQL服务器通过权限表来控制用户对数据库的访问,权限表存放在mysql数据库里,由mysql_install_db脚本初始化。这些权限表分别user,db,table_priv,columns_priv和host。下面分别介绍一下这些表的结构和内容:


user权限表:记录允许连接到服务器的用户帐号信息,里面的权限是全局级的。

db权限表:记录各个帐号在各个数据库上的操作权限。

table_priv权限表:记录数据表级的操作权限。

columns_priv权限表:记录数据列级的操作权限。

host权限表:配合db权限表对给定主机上数据库级操作权限作更细致的控制。这个权限表不受GRANT和REVOKE语句的影响。

5、MySQL由哪些部分组成?

(1)Server


连接器:管理连接、权限验证


分析器:词法分析,语法分析


优化器:执行计划生成,索引的选择


执行器:操作存储引擎,返回执行结果


(2)存储引擎


存储数据,提供读写接口。


6、优化数据库的方法

(1)选取最合适的字段,尽可能减少定义阻断宽度,尽量NOTNULL。


(2)使用JOIN(连接)来代替子查询。


(3)使用UNION(联合)来代替手动创建临时表。


(4)事务处理。


(5)锁定表,优化事务处理。


(6)使用外键,优化锁定表。


(7)建立索引。


(8)优化查询语句。


优化查询过程中的数据访问

访问数据太多导致查询性能下降

确定应用程序是否在检索大量超过需要的数据,可能是太多行或列

确认MySQL服务器是否在分析大量不必要的数据行

避免犯如下SQL语句错误

查询不需要的数据。解决办法:使用limit解决

多表关联返回全部列。解决办法:指定列名

总是返回全部列。解决办法:避免使用SELECT *

重复查询相同的数据。解决办法:可以缓存数据,下次直接读取缓存

是否在扫描额外的记录。解决办法:

使用explain进行分析,如果发现查询需要扫描大量的数据,但只返回少数的行,可以通过如下技巧去优化:

使用索引覆盖扫描,把所有的列都放到索引中,这样存储引擎不需要回表获取对应行就可以返回结果。

改变数据库和表的结构,修改数据表范式

重写SQL语句,让优化器可以以更优的方式执行查询。

优化长难的查询语句

一个复杂查询还是多个简单查询

MySQL内部每秒能扫描内存中上百万行数据,相比之下,响应数据给客户端就要慢得多

使用尽可能小的查询是好的,但是有时将一个大的查询分解为多个小的查询是很有必要的。

切分查询

将一个大的查询分为多个小的相同的查询

一次性删除1000万的数据要比一次删除1万,暂停一会的方案更加损耗服务器开销。

分解关联查询,让缓存的效率更高。

执行单个查询可以减少锁的竞争。

在应用层做关联更容易对数据库进行拆分。

查询效率会有大幅提升。

较少冗余记录的查询。

优化特定类型的查询语句

count()会忽略所有的列,直接统计所有列数,不要使用count(列名)

MyISAM中,没有任何where条件的count(*)非常快。

当有where条件时,MyISAM的count统计不一定比其它引擎快。

可以使用explain查询近似值,用近似值替代count(*)

增加汇总表

使用缓存

优化关联查询

确定ON或者USING子句中是否有索引。

确保GROUP BY和ORDER BY只有一个表中的列,这样MySQL才有可能使用索引。

优化子查询

用关联查询替代


优化GROUP BY和DISTINCT

这两种查询据可以使用索引来优化,是最有效的优化方法

关联查询中,使用标识列分组的效率更高

如果不需要ORDER BY,进行GROUP BY时加ORDER BY NULL,MySQL不会再进行文件排序。

WITH ROLLUP超级聚合,可以挪到应用程序处理

优化LIMIT分页

LIMIT偏移量大的时候,查询效率较低

可以记录上次查询的最大ID,下次查询时直接根据该ID来查询

优化UNION查询

UNION ALL的效率高于UNION


7、解释一下交叉连接、内连接、外连接

(1)交叉连接(笛卡尔积):不使用任何条件,直接将一个表的所有记录和另一个表中的所有记录一一匹配。


(2)内连接:只有条件的交叉连接,根据某个条件筛选出符合的记录。


(3)外连接:不仅包含符合连接条件的行,而且还会包括左表、右表或两个表中的所有数据行。


六种关联查询

交叉连接(CROSS JOIN)

内连接(INNER JOIN)

外连接(LEFT JOIN/RIGHT JOIN)

联合查询(UNION与UNION ALL)

全连接(FULL JOIN)

外连接(LEFT JOIN/RIGHT JOIN)

左外连接:LEFT OUTER JOIN, 以左表为主,先查询出左表,按照ON后的关联条件匹配右表,没有匹配到的用NULL填充,可以简写成LEFT JOIN

右外连接:RIGHT OUTER JOIN, 以右表为主,先查询出右表,按照ON后的关联条件匹配左表,没有匹配到的用NULL填充,可以简写成RIGHT JOIN


联合查询(UNION与UNION ALL)

就是把多个结果集集中在一起,UNION前的结果为基准,需要注意的是联合查询的列数要相等,相同的记录行会合并

如果使用UNION ALL,不会合并重复的记录行

效率 UNION 高于 UNION ALL

全连接(FULL JOIN)

MySQL不支持全连接

可以使用LEFT JOIN 和UNION和RIGHT JOIN联合使用

8、为什么要使用NOTNULL?

Null值会占用更多的字节,并且会在程序中造成很多与预期不符的结果。


9、什么是索引?

是一种数据结构,可以帮助我们快速的进行数据的查找。


数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。


更通俗的说,索引就相当于目录。为了方便查找书中的内容,通过对内容建立索引形成目录。


索引是一个文件,它是要占据物理空间的。


优点:(1)提高数据检索的效率,降低数据库的IO成本。


(2)通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消耗。


缺点:(1)降低更新表的速度。


(2)索引也是一张表,该表保存了主键与索引字段,并且指向实体表的记录,所以索引表也需要占用空间。


(3)创建索引和维护索引需要消耗时间,并且随着数据了的增加,所消耗的时间也会增加。


索引有哪几种类型?

主键索引: 数据列不允许重复,不允许为NULL,一个表只能有一个主键。


唯一索引: 数据列不允许重复,允许为NULL值,一个表允许多个列创建唯一索引。


普通索引: 基本的索引类型,没有唯一性的限制,允许为NULL值。


全文索引: 是目前搜索引擎使用的一种关键技术。


索引的基本原理

把创建了索引的列的内容进行排序

对排序结果生成倒排表

在倒排表内容上拼上数据地址链

在查询的时候,先拿到倒排表内容,再取出数据地址链,从而拿到具体数据

索引设计的原则?

适合索引的列是出现在where子句中的列,或者连接子句中指定的列

基数较小的类,索引效果较差,没有必要在此列建立索引

使用短索引,如果对长字符串列进行索引,应该指定一个前缀长度,这样能够节省大量索引空间

不要过度索引。索引需要额外的磁盘空间,并降低写操作的性能。在修改表内容的时候,索引会进行更新甚至重构,索引列越多,这个时间就会越长。所以只保持需要的索引有利于查询即可。

创建索引的原则(重中之重)

索引虽好,但也不是无限制的使用,最好符合一下几个原则


1) 最左前缀匹配原则,组合索引非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。


2)较频繁作为查询条件的字段才去创建索引


3)更新频繁字段不适合创建索引


4)若是不能有效区分数据的列不适合做索引列(如性别,男女未知,最多也就三种,区分度实在太低)


5)尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。


6)定义有外键的数据列一定要建立索引。


7)对于那些查询中很少涉及的列,重复值比较多的列不要建立索引。


8)对于定义为text、image和bit的数据类型的列不要建立索引。


使用索引查询一定能提高查询的性能吗?为什么

通常,通过索引查询数据比全表扫描要快。但是我们也必须注意到它的代价。


索引需要空间来存储,也需要定期维护, 每当有记录在表中增减或索引列被修改时,索引本身也会被修改。 这意味着每条记录的INSERT,DELETE,UPDATE将为此多付出4,5 次的磁盘I/O。 因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢。使用索引查询不一定能提高查询性能,索引范围查询(INDEX RANGE SCAN)适用于两种情况:

基于一个范围的检索,一般查询返回结果集小于表中记录数的30%

基于非唯一性索引的检索

10、什么是事务?

事务是一个不可分割的数据库操作序列,也是数据库并发控制的基本单位,其执行的结果必须使数据库从一种一致性状态变到另一种一致性状态。事务是逻辑上的一组操作,要么都执行,要么都不执行。


MySQL 事务隔离级别

未提交读 - 读到其它事务未提交的数据(最新的版本)

错误现象:有脏读、不可重复读、幻读现象

提交读(RC) - 读到其它事务已提交的数据(最新已提交的版本)

错误现象:有不可重复读、幻读现象

使用场景:希望看到最新的有效值

可重复读(RR) - 在事务范围内,多次读能够保证一致性(快照建立时最新已提交版本)

错误现象:有幻读现象,可以用加锁避免

使用场景:事务内要求更强的一致性,但看到的未必是最新的有效值

串行读 - 在事务范围内,仅有读读可以并发,读写或写写会阻塞其它事务,用这种办法保证更强的一致性

错误现象:无

11、ACID事务的特性

image-20230206131028026.png

原子性:事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;


一致性: 执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的;


隔离性:并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;


持久性:一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。


12、并发事务带来了哪些问题?

(1)脏读:一个事务对数据进行了修改,还未提交到数据库;另一个事务使用了未修改的数据,依据这个脏数据所做的操作可能是不正确的。


(2)丢失修改:两个事务同时访问并修改同一个数据,那么第一个事务修改的结果就会被丢失。


(3)不可重复读:在一个事务内多次读取同一数据。在这个事务结束之前,另一个事务进修改了数据,那么第一个事务两次读取的数据就会不一样了。


(4)幻读:发生在一个事务读取了几行数据,接着另一个并发事务插入了一些数据,在随后的查询中,第一个事务就会发现多了一些原本不存在的数据。


13、MySQL的四种隔离级别

936796388da8b7ce9e25df7d074835c5.png


(1)读未提交:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。


(2)读已提交:允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。


(3)可重复读:对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。


(4)可串行化:最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。


隔离级别与锁的关系

在Read Uncommitted级别下,读取数据不需要加共享锁,这样就不会跟被修改的数据上的排他锁冲突


在Read Committed级别下,读操作需要加共享锁,但是在语句执行完以后释放共享锁;


在Repeatable Read级别下,读操作需要加共享锁,但是在事务提交之前并不释放共享锁,也就是必须等待事务执行完毕以后才释放共享锁。


SERIALIZABLE 是限制性最强的隔离级别,因为该级别锁定整个范围的键,并一直持有锁,直到事务完成。


14、MySQL存储引擎MyISAM与InnoDB区别

存储引擎Storage engine:MySQL中的数据、索引以及其他对象是如何存储的,是一套文件系统的实现。


常用的存储引擎有以下:


Innodb引擎:Innodb引擎提供了对数据库ACID事务的支持。并且还提供了行级锁和外键的约束。它的设计的目标就是处理大数据容量的数据库系统。

MyIASM引擎(原本Mysql的默认引擎):不提供事务的支持,也不支持行级锁和外键。

MEMORY引擎:所有的数据都在内存中,数据的处理速度快,但是安全性不高。

MyISAM索引与InnoDB索引的区别?

InnoDB索引是聚簇索引,MyISAM索引是非聚簇索引。

InnoDB的主键索引的叶子节点存储着行数据,因此主键索引非常高效。

MyISAM索引的叶子节点存储的是行数据地址,需要再寻址一次才能得到数据。

InnoDB非主键索引的叶子节点存储的是主键和其他带索引的列数据,因此查询时做到覆盖索引会非常高效。

MyISAM与InnoDB区别

InnoDB支持事务,MyISAM不支持事务

InnoDB支持外键,MyISAM不支持外键

InnoDB 支持 MVCC(多版本并发控制),MyISAM 不支持

select count(*) from table时,MyISAM更快,因为它有一个变量保存了整个表的总行数,可以直接读取,InnoDB就需要全表扫描。

Innodb不支持全文索引,而MyISAM支持全文索引(5.7以后的InnoDB也支持全文索引)

InnoDB支持表、行级锁,而MyISAM支持表级锁。

InnoDB表必须有主键,而MyISAM可以没有主键

Innodb表需要更多的内存和存储,而MyISAM可被压缩,存储空间较小,。

Innodb按主键大小有序插入,MyISAM记录插入顺序是,按记录插入顺序保存。

InnoDB 存储引擎提供了具有提交、回滚、崩溃恢复能力的事务安全,与 MyISAM 比 InnoDB 写的效率差一些,并且会占用更多的磁盘空间以保留数据和索引

InnoDB引擎的4大特性

插入缓冲(insert buffer)

二次写(double write)

自适应哈希索引(ahi)

预读(read ahead)

15、百万级别或以上的数据如何删除

所以我们想要删除百万数据的时候可以先删除索引(此时大概耗时三分多钟)

然后删除其中无用数据(此过程需要不到两分钟)

删除完成后重新创建索引(此时数据较少了)创建索引也非常快,约十分钟左右。

与之前的直接删除绝对是要快速很多,更别说万一删除中断,一切删除会回滚。那更是坑了。

16、数据库为什么使用B+树而不是B树

B树只适合随机检索

B+树空间利用率更高,可减少I/O次数,磁盘读写代价更低。

B+树的查询效率更加稳定。

B树在提高了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题。

增删文件(节点)时,效率更高。

17、对MySQL的锁了解吗?

当数据库有并发事务的时候,可能会产生数据的不一致,这时候需要一些机制来保证访问的次序,锁机制就是这样的一个机制。


什么是死锁?怎么解决?

死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方的资源,从而导致恶性循环的现象。


常见的解决死锁的方法


1、如果不同程序会并发存取多个表,尽量约定以相同的顺序访问表,可以大大降低死锁机会。


2、在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率;


3、对于非常容易产生死锁的业务部分,可以尝试使用升级锁定颗粒度,通过表级锁定来减少死锁产生的概率;


如果业务处理不好可以用分布式事务锁或者使用乐观锁


数据库的乐观锁和悲观锁是什么?怎么实现的?


数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性。乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段。


悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。在查询完数据的时候就把事务锁起来,直到提交事务。实现方式:使用数据库中的锁机制


乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。在修改数据的时候把事务锁起来,通过version的方式来进行锁定。实现方式:乐一般会使用版本号机制或CAS算法实现。


18、为什么要使用视图?什么是视图?

为了提高复杂SQL语句的复用性和表操作的安全性。


一种虚拟表,在物理上是不存在的,其内容与真实的表相似,包含一系列带有名称的列和行数据。


视图并不在数据库中以储存的数据值形式存在。行和列数据来自定义视图的查询所引用基本表,并且在具体引用视图时动态生成。


19、视图有哪些特点?

视图的列可以来自不同的表,是表的抽象和在逻辑意义上建立的新关系。

视图是由基本表(实表)产生的表(虚表)。

视图的建立和删除不影响基本表。

对视图内容的更新(添加,删除和修改)直接影响基本表。

当视图来自多个基本表时,不允许添加和删除数据。

20、视图的使用场景有哪些?

重用SQL语句;

简化复杂的SQL操作。在编写查询后,可以方便的重用它而不必知道它的基本查询细节;

使用表的组成部分而不是整个表;

保护数据。可以给用户授予表的特定部分的访问权限而不是整个表的访问权限;

更改数据格式和表示。视图可返回与底层表的表示和格式不同的数据。

21、视图的优点

查询简单化。视图能简化用户的操作

数据安全性。视图使用户能以多种角度看待同一数据,能够对机密数据提供安全保护

逻辑数据独立性。视图对重构数据库提供了一定程度的逻辑独立性

22、视图的缺点

性能。数据库必须把视图的查询转化成对基本表的查询,如果这个视图是由一个复杂的多表查询所定义,那么,即使是视图的一个简单查询,数据库也把它变成一个复杂的结合体,需要花费一定的时间。


修改限制。当用户试图修改视图的某些行时,数据库必须把它转化为对基本表的某些行的修改。事实上,当从视图中插入或者删除时,情况也是这样。对于简单视图来说,这是很方便的,但是,对于比较复杂的视图,可能是不可修改的


这些视图有如下特征:1.有UNIQUE等集合操作符的视图。2.有GROUP BY子句的视图。3.有诸如AVG\SUM\MAX等聚合函数的视图。 4.使用DISTINCT关键字的视图。5.连接表的视图(其中有些例外)


23、存储过程与函数

什么是存储过程?有哪些优缺点?

存储过程是一个预编译的SQL语句,优点是允许模块化的设计,就是说只需要创建一次,以后在该程序中就可以调用多次。如果某次操作需要执行多次SQL,使用存储过程比单纯SQL语句执行要快。


优点


1)存储过程是预编译过的,执行效率高。


2)存储过程的代码直接存放于数据库中,通过存储过程名直接调用,减少网络通讯。


3)安全性高,执行存储过程需要有一定权限的用户。


4)存储过程可以重复使用,减少数据库开发人员的工作量。


缺点


1)调试麻烦,但是用 PL/SQL Developer 调试很方便!弥补这个缺点。


2)移植问题,数据库端代码当然是与数据库相关的。但是如果是做工程型项目,基本不存在移植问题。


3)重新编译问题,因为后端代码是运行前编译的,如果带有引用关系的对象发生改变时,受影响的存储过程、包将需要重新编译(不过也可以设置成运行时刻自动编译)。


4)如果在一个程序系统中大量的使用存储过程,到程序交付使用的时候随着用户需求的增加会导致数据结构的变化,接着就是系统的相关问题了,最后如果用户想维护该系统可以说是很难很难、而且代价是空前的,维护起来更麻烦。


24、什么是触发器?触发器的使用场景有哪些?

触发器是用户定义在关系表上的一类由事件驱动的特殊的存储过程。触发器是指一段代码,当触发某个事件时,自动执行这些代码。


使用场景


可以通过数据库中的相关表实现级联更改。

实时监控某张表中的某个字段的更改而需要做出相应的处理。

例如可以生成某些业务的编号。

注意不要滥用,否则会造成数据库及应用程序的维护困难。

大家需要牢记以上基础知识点,重点是理解数据类型CHAR和VARCHAR的差异,表存储引擎InnoDB和MyISAM的区别。

25、超键、候选键、主键、外键分别是什么?

超键:在关系中能唯一标识元组的属性集称为关系模式的超键。一个属性可以为作为一个超键,多个属性组合在一起也可以作为一个超键。超键包含候选键和主键。

候选键:是最小超键,即没有冗余元素的超键。

主键:数据库表中对储存数据对象予以唯一和完整标识的数据列或属性的组合。一个数据列只能有一个主键,且主键的取值不能缺失,即不能为空值(Null)。

外键:在一个表中存在的另一个表的主键称此表的外键。

26、什么是子查询?

条件:一条SQL语句的查询结果做为另一条查询语句的条件或查询结果

嵌套:多条SQL语句嵌套使用,内部的SQL查询语句称为子查询。

27、mysql中 in 和 exists 区别?

mysql中的in语句是把外表和内表作hash 连接,而exists语句是对外表作loop循环,每次loop循环再对内表进行查询。一直大家都认为exists比in语句的效率要高,这种说法其实是不准确的。这个是要区分环境的。


28、大表数据查询,怎么优化?

优化shema、sql语句+索引;

第二加缓存,memcached, redis;

主从复制,读写分离;

垂直拆分,根据你模块的耦合度,将一个大的系统分为多个小的系统,也就是分布式系统;

水平切分,针对数据量大的表,这一步最麻烦,最能考验技术水平,要选择一个合理的sharding key, 为了有好的查询效率,表结构也要改动,做一定的冗余,应用也要改,sql中尽量带sharding key,将数据定位到限定的表上去查,而不是扫描全部的表;

29、超大分页怎么处理?

数据库层面,这也是我们主要集中关注的(虽然收效没那么大),类似于select * from table where age > 20 limit 1000000,10这种查询其实也是有可以优化的余地的. 这条语句需要load1000000数据然后基本上全部丢弃,只取10条当然比较慢. 当时我们可以修改为select * from table where id in (select id from table where age > 20 limit 1000000,10).这样虽然也load了一百万的数据,但是由于索引覆盖,要查询的所有字段都在索引中,所以速度会很快. 同时如果ID连续的好,我们还可以select * from table where id > 1000000 limit 10,效率也是不错的,优化的可能性有许多种,但是核心思想都一样,就是减少load的数据.

从需求的角度减少这种请求…主要是不做类似的需求(直接跳转到几百万页之后的具体某一页.只允许逐页查看或者按照给定的路线走,这样可预测,可缓存)以及防止ID泄漏且连续被人恶意攻击.

30、关心过业务系统里面的sql耗时吗?统计过慢查询吗?对慢查询都怎么优化过?

首先分析语句,看看是否load了额外的数据,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写。

分析语句的执行计划,然后获得其使用索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引。

如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表。

31、CHAR 和VARCHAR 的区别?

CHAR 和 VARCHAR 类型在存储和检索方面有所不同

CHAR 列长度固定为创建表时声明的长度, 长度值范围是 1 到 255 当 CHAR 值被存储时, 它们被用空格填充到特定长度, 检索 CHAR 值时需删除尾随空格。

32、数据库索引的原理,为什么要用B+树,为什么不用二叉树?

为什么不是一般二叉树?


如果二叉树特殊化为一个链表,相当于全表扫描。平衡二叉树相比于二叉查找树来说,查找效率更稳定,总体的查找速度也更快。


为什么不是平衡二叉树呢?


我们知道,在内存比在磁盘的数据,查询效率快得多。如果树这种数据结构作为索引,那我们每查找一次数据就需要从磁盘中读取一个节点,也就是我们说的一个磁盘块,但是平衡二叉树可是每个节点只存储一个键值和数据的,如果是B树,可以存储更多的节点数据,树的高度也会降低,因此读取磁盘的次数就降下来啦,查询效率就快啦。


那为什么不是B树而是B+树呢?


B+树非叶子节点上是不存储数据的,仅存储键值,而B树节点中不仅存储键值,也会存储数据。innodb中页的默认大小是16KB,如果不存储数据,那么就会存储更多的键值,相应的树的阶数(节点的子节点树)就会更大,树就会更矮更胖,如此一来我们查找数据进行磁盘的IO次数有会再次减少,数据查询的效率也会更快。

B+树索引的所有数据均存储在叶子节点,而且数据是按照顺序排列的,链表连着的。那么B+树使得范围查找,排序查找,分组查找以及去重查找变得异常简单。

33、数据库自增主键可能遇到什么问题

使用自增主键对数据库做分库分表,可能出现诸如主键重复等的问题。解决方案的话,简单点的话可以考虑使用UUID解决,复杂的可以考虑前面提到的分布式主键方案

自增主键会产生表锁,从而引发问题

自增主键可能用完问题。

34、Blob和text有什么区别?

Blob用于存储二进制数据,而Text用于存储大字符串。

Blob值被视为二进制字符串(字节字符串),它们没有字符集,并且排序和比较基于列值中的字节的数值。

text值被视为非二进制字符串(字符字符串)。它们有一个字符集,并根据字符集的排序规则对值进行排序和比较

35、count(1)、count(*) 与 count(列名) 的区别?

count(*):包括了所有的列,相当于行数,在统计结果的时候,不会忽略列值为NULL

count(1):包括了忽略所有列,用1代表代码行,在统计结果的时候,不会忽略列值为NULL

count(列名):只包括列名那一列,在统计结果的时候,会忽略列值为空(这里的空不是指空字符串或者0,而是表示null)的计数,即某个字段值为NULL时,不统计。

36、查询语句执行流程

e33e217fac5dbc35ce89f87665c6f1ad.png


连接器:负责建立连接、检查权限、连接超时时间由 wait_timeout 控制,默认 8 小时

查询缓存:会将 SQL 和查询结果以键值对方式进行缓存,修改操作会以表单位导致缓存失效

分析器:词法、语法分析

优化器:决定用哪个索引,决定表的连接顺序等

执行器:根据存储引擎类型,调用存储引擎接口

存储引擎:数据的读写接口,索引、表都在此层实现

37、MySQL锁

1、全局锁

用作全量备份时,保证表与表之间的数据一致性


如果不加任何包含,数据备份时就可能产生不一致的情况,如下图所示

image-20230206113816398.png


使用全局读锁锁定所有数据库的所有表。这时会阻塞其它所有 DML 以及 DDL 操作,这样可以避免备份过程中的数据不一致。接下来可以执行备份,最后用 unlock tables 来解锁

2、表级锁

1、表锁

语法:加锁 lock tables 表名 read/write,解锁 unlock tables

缺点:粒度较粗,在 InnoDB 引擎很少使用

2、元数据锁

即 metadata-lock(MDL),主要是为了避免 DML 与 DDL 冲突,DML 的元数据锁之间不互斥


加元数据锁的几种情况


lock tables read/write,类型为 SHARED_READ_ONLY 和 SHARED_NO_READ_WRITE

alter table,类型为 EXCLUSIVE,与其它 MDL 都互斥

select,select … lock in share mode,类型为 SHARED_READ

insert,update,delete,select for update,类型为 SHARED_WRITE

查看元数据锁(适用于 MySQL 8.0 以上版本)


select object_type,object_schema,object_name,lock_type,lock_duration from performance_schema.metadata_locks;


3、行级锁

种类

行锁 – 在 RC 下,锁住的是行,防止其他事务对此行 update 或 delete

间隙锁 – 在 RR 下,锁住的是间隙,防止其他事务在这个间隙 insert 产生幻读

临键锁 – 在 RR 下,锁住的是前面间隙+行,特定条件下可优化为行锁

查看行级锁

select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks where object_name='表名';

注意


它们锁定的其实都是索引上的行与间隙,根据索引的有序性来确定间隙

38、什么是最左前缀原则?什么是最左匹配原则

顾名思义,就是最左优先,在创建多列索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边。

最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。

=和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式

39、什么是聚簇索引?何时使用聚簇索引与非聚簇索引

聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据

非聚簇索引:将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行,myisam通过key_buffer把索引先缓存到内存中,当需要访问数据时(通过索引访问数据),在内存中直接搜索索引,然后通过索引找到磁盘相应数据,这也就是为什么索引不在key buffer命中时,速度慢的原因。

40、联合索引是什么?为什么需要注意联合索引中的顺序?

MySQL可以使用多个字段同时建立一个索引,叫做联合索引。在联合索引中,如果想要命中索引,需要按照建立索引时的字段顺序挨个使用,否则无法命中索引。


具体原因为:


MySQL使用索引时需要索引有序,假设现在建立了"name,age,school"的联合索引,那么索引的排序为: 先按照name排序,如果name相同,则按照age排序,如果age的值也相等,则按照school进行排序。


当进行查询时,此时索引仅仅按照name严格有序,因此必须首先使用name字段进行等值查询,之后对于匹配到的列而言,其按照age字段严格有序,此时可以使用age字段用做索引查找,以此类推。因此在建立联合索引的时候应该注意索引列的顺序,一般情况下,将查询需求频繁或者字段选择性高的列放在前面。此外可以根据特例的查询或者表结构进行单独的调整。


41、SQL语句主要分为哪几类

数据定义语言DDL(Data Ddefinition Language)CREATE,DROP,ALTER


主要为以上操作 即对逻辑结构等有操作的,其中包括表结构,视图和索引。


数据查询语言DQL(Data Query Language)SELECT


这个较为好理解 即查询操作,以select关键字。各种简单查询,连接查询等 都属于DQL。


数据操纵语言DML(Data Manipulation Language)INSERT,UPDATE,DELETE


主要为以上操作 即对数据进行操作的,对应上面所说的查询操作 DQL与DML共同构建了多数初级程序员常用的增删改查操作。而查询是较为特殊的一种 被划分到DQL中。


数据控制功能DCL(Data Control Language)GRANT,REVOKE,COMMIT,ROLLBACK


主要为以上操作 即对数据库安全性完整性等有操作的,可以简单的理解为权限控制等。


42、超键、候选键、主键、外键分别是什么?

超键:在关系中能唯一标识元组的属性集称为关系模式的超键。一个属性可以为作为一

超键,多个属性组合在一起也可以作为一个超键。超键包含候选键和主键。

候选键:是最小超键,即没有冗余元素的超键。

主键:数据库表中对储存数据对象予以唯一和完整标识的数据列或属性的组合。一个数据列只能有一个主键,且主键的取值不能缺失,即不能为空值(Null)。

外键:在一个表中存在的另一个表的主键称此表的外键。

43、SQL 约束有哪几种?

NOT NULL: 用于控制字段的内容一定不能为空(NULL)。

UNIQUE: 控件字段内容不能重复,一个表允许有多个 Unique 约束。

PRIMARY KEY: 也是用于控件字段内容不能重复,但它在一个表只允许出现一个。

FOREIGN KEY: 用于预防破坏表之间连接的动作,也能防止非法数据插入外键列,因为它必须是它指向的那个表中的值之一。

CHECK: 用于控制字段的值范围。

44、varchar(50)中50的涵义

最多存放50个字符,varchar(50)和(200)存储hello所占空间一样,但后者在排序时会消耗更多内存,因为order by col采用fixed_length计算col长度(memory引擎也一样)。在早期 MySQL 版本中, 50 代表字节数,现在代表字符数。


45、int(20)中20的涵义

是指显示字符的长度。20表示最大显示宽度为20,但仍占4字节存储,存储范围不变;


不影响内部存储,只是影响带 zerofill 定义的 int 时,前面补多少个 0,易于报表展示


46、为什么要尽量设定一个主键?

主键是数据库确保数据行在整张表唯一性的保障,即使业务上本张表没有主键,也建议添加一个自增长的ID列作为主键。设定了主键之后,在后续的删改查的时候可能更加快速以及确保操作数据范围安全。


47、MySQL的复制原理以及流程

主从复制:将主数据库中的DDL和DML操作通过二进制日志(BINLOG)传输到从数据库上,然后将这些日志重新执行(重做);从而使得从数据库的数据与主数据库保持一致。


48、MySQL主从复制的作用

主数据库出现问题,可以切换到从数据库。

可以进行数据库层面的读写分离。

可以在从数据库上进行日常备份。

49、MySQL主从复制工作原理

在主库上把数据更高记录到二进制日志

从库将主库的日志复制到自己的中继日志

从库读取中继日志的事件,将其重放到从库数据中

50、什么是死锁?怎么解决?

死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方的资源,从而导致恶性循环的现象。


常见的解决死锁的方法


1、如果不同程序会并发存取多个表,尽量约定以相同的顺序访问表,可以大大降低死锁机会。


2、在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率;


3、对于非常容易产生死锁的业务部分,可以尝试使用升级锁定颗粒度,通过表级锁定来减少死锁产生的概率;


如果业务处理不好可以用分布式事务锁或者使用乐观锁


51、数据库的乐观锁和悲观锁是什么?怎么实现的?

数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性。乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段。


悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。在查询完数据的时候就把事务锁起来,直到提交事务。实现方式:使用数据库中的锁机制


乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。在修改数据的时候把事务锁起来,通过version的方式来进行锁定。实现方式:乐观锁一般会使用版本号机制或CAS算法实现。


两种锁的使用场景


从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。


但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以一般多写的场景下用悲观锁就比较合适。


51、drop、delete与truncate的区别

三者都是表示删除,但是三者都有一些差别:

image-20230207095219639.png


因此,在不再需要一张表的时候,用drop;在想删除部分数据行时候,用 delete;在保留表而删除所有数据的时候用truncate。

52、UNION与UNIONALL的区别?

如果使用UNION ALL,不会合并重复的记录行 效率 UNION 高于 UNION ALL


53、按照锁的粒度分数据库锁有哪些?

在关系型数据库中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎)、表级锁(MYISAM引擎)和页级锁(BDB引擎 )。


MyISAM和InnoDB存储引擎使用的锁:


MyISAM采用表级锁(table-level locking)。


InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁


行级锁,表级锁和页级锁对比


行级锁 行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大。行级锁分为共享锁 和 排他锁。

特点:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

表级锁 表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MYISAM与INNODB都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)。

特点:开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。

页级锁 页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。

特点:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般

54、数据库中有六种触发器

Before Insert

After Insert

Before Update

After Update

Before Delete

After Delete

55、Hash索引和B+树索引有什么区别或者说优劣呢?

首先要知道Hash索引和B+树索引的底层实现原理:


hash索引底层就是hash表,进行查找时,调用一次hash函数就可以获取到相应的键值,之后进行回表查询获得实际数据.B+树底层实现是多路平衡查找树.对于每一次的查询都是从根节点出发,查找到叶子节点方可以获得所查键值,然后根据查询判断是否需要回表查询数据.


那么可以看出他们有以下的不同:hash索引进行等值查询更快(一般情况下),但是却无法进行范围查询.


因为在hash索引中经过hash函数建立索引之后,索引的顺序与原顺序无法保持一致,不能支持范围查询.而B+树的的所有节点皆遵循(左节点小于父节点,右节点大于父节点,多叉树也类似),天然支持范围.


hash索引不支持使用索引进行排序,原理同上.


hash索引不支持模糊查询以及多列索引的最左前缀匹配.原理也是因为hash函数的不可预测.AAAA和AAAAB的索引没有相关性.


hash索引任何时候都避免不了回表查询数据,而B+树在符合某些条件(聚簇索引,覆盖索引等)的时候可以只通过索引完成查询.


hash索引虽然在等值查询上较快,但是不稳定.性能不可预测,当某个键值存在大量重复的时候,发生hash碰撞,此时效率可能极差.而B+树的查询效率比较稳定,对于所有的查询都是从根节点到叶子节点,且树的高度较低.


因此,在大多数情况下,直接选择B+树索引可以获得稳定且较好的查询速度.而不需要使用hash索引.


目录
相关文章
|
安全
病理学知识点整理
病理学知识点整理
73 0
|
NoSQL Java 关系型数据库
面试题整理
面试题整理
61 0
|
消息中间件 缓存 Java
常见面试题整理(2022-11)
常见面试题整理(2022-11)
60 0
|
缓存 JavaScript 前端开发
前端面试题整理?
前端面试题整理?
|
缓存 前端开发 JavaScript
前端面试题大全整理中...
前端面试题大全整理中...
75 0
|
存储 消息中间件 缓存
面试题整理(五)
面试题整理(五)
253 0
|
SQL 存储 缓存
面试题整理(四)
面试题整理(四)
240 0
|
存储 XML 安全
面试题整理(一)
面试题整理(一)
186 0
|
存储 NoSQL 网络协议
面试题整理(六)
面试题整理(六)
177 0
|
存储 监控 安全
面试题整理(二)
面试题整理(二)
131 0