背点八股
1、在Mysql的分布式环境中,为什么不推荐使用自增主键?
--自增主键在分布式环境下有严重问题,例如有一张商品表:
有3个表分片,分别是表分片1(0-1亿),表分片2(1-2亿),表分片3(2-3亿)

自增主键必须连续,只能采用‘范围分片’形式,会产生‘尾部热点’效应
--当有表A、B、C三个数据库时,存储数据时都是通过自增来进行存储的,那么当A库没有存满时,那么B库和C库就不会存储数据,那么某一个时间段,数据库的压力是集中在其中一个数据库的,并没有做到负载均衡
--当我们将数据同步到其他库的时候,那么由于采用了自增ID,在进行插入的过程中,入非常损耗性能,因为在同步过程中是加锁来进行实现的
--每个库都维护一份自己的自增序列,那么当进行跨库查询的时候,就会产生ID重合的冲突。
2、UUID可以用来做主键吗?会存在什么问题?
--UUID是不能用来作为主键的,因为UUID是无序的,作为主键会涉及大量的索引重排
3、雪花算法可以用做主键吗?原理是什么?有什么优缺点?如何解决缺点?
--可以用来作为主键
是由符号位+时间戳+工作进程+序列号位的自增组成
优点:1、不会重复
2、有序 不会造成空间浪费
3、生成速度快
缺点:1、依赖机器时钟,如果机器时钟回拨,会导致重复ID生成
2、在单机上是递增的但是由于涉及到分布式环境,每个机器的时钟不可能完全同步,有时会出现不是全部递增的
--解决:
时钟回拨问题的解决思路:
1、直接抛出异常
if (currentTimestamp < lastTimestamp) { throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - currentTimestamp)); }
2、使用Map<machine_id,max_id>保存过去一段时间内每一台机器在当前这一毫秒产生的ID的最大值,当某台机器发生时钟回拨,直接在这台机器对应的max_id的基础上继续自增生成ID
3、将原本10位机器码拆分成3位时钟序列及机器码,发生变化,那么这时将时钟序列新增一位,重新定义整个雪花id,同时为了避免实例重启引用时间序列丢失,因此时钟序列存到DB或者缓存中
`// 处理时间回拨
if (currentTimestamp < lastTimestamp) {
clockSequence = (clockSequence + 1) & CLOCK_SEQUENCE_MASK;
}
4、什么是回表?如何避免回表?
--MySQL 中的"回表"是指在查询数据时,需要先通过索引定位到主键值,然后再通过主键定位到实际的行记录。这个过程通常需要扫描两次索引树,因此性能相对较低。
--MySQL中使用了B+树索引结构来加速数据的查找,B+树是一种多叉树,它的叶子节点中存储了完整的数据行,而非叶子节点则存储了索引的键值和指向下一级节点的指针。
--索引查询:当执行一个查询语句时,MySQL会首先根据查询条件从B+树的根节点开始进行查找,逐层下降直到找到满足条件的叶子节点,如果查询条件匹配了索引的键值,则可以直接从叶子节点中获取到完整的数据行,无需回表。
--回表则是因为在某些条件下,索引无法提供查询所需的所有信息,这时候就需要进行回表操作,例如:如果查询语句需要返回的字段不在索引中,或者查询条件需要使用索引之外的字段,就会发生回表。
--回表的过程:MySQL会根据叶子节点中的主键值再次去数据表中查找对应的数据行,以获取到缺失的数据,这个会增加额外的IO消耗和网络传输时间,降低查询性能。
--针对回表的优化:使用覆盖索引来包含查询语句所需的所有字段,避免回表操作,或者使用索引的聚簇特性,将相关的字段放在一起,减少回表的次数。
--回表出现的场景:
1、需要查询的字段不在索引中,当查询语句需要返回的字段不在索引中时,就会发生回表,例如:如果索引中只包含了用户的ID,而查询语句需要返回用户的姓名和年龄,就需要进行回表操作。
2、使用非索引字段进行查询。
3、覆盖索引不可用,通常发生在查询需要大量字段或者字段类型较大的情况下。
4、查询结果需要排序或者分组,因为排序或者分组需要对完整的数据进行操作。
5、索引选择性低,即索引中的键值重复比较多,那么在进行查询时,可能会有多条数据落在同一个叶子节点上,这就会回表。
CREATE INDEX idx_name_age ON student (name,age);
SELECT name,age FROM student WHERE name='Alice';
回表不一定是性能问题的根本原因,有时候回表无法避免,但是在一些特定场景下,可以通过优化查询语句,设计合适的索引或者调整数据库的配置来减少回表的次数
5、java中的强引用、软引用、弱引用、虚引用
--1、通过代码的方式决定某个对象的声明周期
--2、有利于垃圾回收机制进行垃圾回收
--什么是强引用?
Tiger tiger=new Tiger("sss");这就属于强引用
--什么是软引用?
使用SoftReference进行包裹
SoftReference<Tiger> softReference=new SoftReference<>(new Tiger());
Tiger tiger=softReference.get();
但内存不足或者堆内存不足的时候,会触发JVM的GC,如果GC之后内存还是不足,就会把软引用的包裹对象干掉,只有在内存不足的情况下才会回收对象。
6、一条更新语句的执行过程?
--更新语句的执行过程"update user set name=xiaoming where id=1"
1、首先是客户端咸鱼mysql的连接器进行连接的创建
2、连接创建完成之后,到达分析器,进行词法或者语法的分析
3、紧接着到达优化器,优化器会生成执行计划,选择索引
4、之后到达执行器,执行器调用存储引擎,返回结果
7、一条查询语句的执行过程?
--select、from、join、where、group by、order by、having这时sql语句顺序
实际上的sql执行顺序:
首先先执行from join来确定表之间的连接关系 得到初步的数据
where对数据进行普通的初步的筛选
group by分组
各组分别执行having中的普通筛选或者聚合函数筛选
然后再根据我们要的数据进行select,可以是普通字段也可以是获取聚合函数结果,如果是集合函数,select的查询结果会新增一条字段
将查询到的结果进行去重distinct
最后合并各组的查询结果,按照order by的条件进行排序
--那么具体的Mysql的执行流程?
1、建立连接
2、查询缓存
3、语法解析和预处理 对sql语句进行词法和语法分析和语义的解析
4、查询优化与查询执行计划
5、存储引擎 如果对数据一致性要求比较高,需要事务支持,可以选择Innodb
6、执行引擎,返回结果

8、mysql的Innodb引擎下都有哪些隔离级别?
--事务管理是确保数据一致性和完整性的关键,事务就是数据库操作的基本单元,它将一些列数据库操作组合成一个逻辑单元,要么全部执行成功,要么全部失败回滚,这就是所谓的ACID,即原子性、一致性、隔离性、持久性
--事务隔离级别和锁机制是维护数据库一致性和并发控制的核心组成部分,事务隔离级别定义了再多个事务同时执行时,各个事务之间的隔离程度,而锁机制是实现这些隔离级别的关键工具,通过锁定数据,确保事务的隔离和并发操作的正确性。
--读未提交
是最低的隔离级别,允许事务读取尚未提交的数据,这种情况下一个事务可以看到另一个事务未提交的数据,可能会导致脏读,(脏读是指一个事务读取另一个事务中未提交的数据,导致数据的不一致性)
--读已提交
是Innodb默认的隔离级别,这个级别下,事务只能去读到已经提交的数据,这样可以避免脏读,但是可能会产生不可重复读。
(不可重复读是在一个事务中,由于其他事务的提交,同一查询可能返回不同的结果)
--可重复读
可以保证同一个事务可以多次读取同一数据,这些数据是一致的,不会出现不可重复读的情况,这意味着即使其他事务对数据进行了修改,事务内读取的数据仍然保持一致,在此情况下,可能会出现幻读的情况。
(幻读是指一个事务在读取了一个范围内的记录后,另一个事务在这个范围内插入了新的记录,导致第一个事务再次读取时,看到了新插入的记录)
--串行化
是最高的隔离级别
避免了所有的并发问题,在这个级别下,每个事务都会按照提交的顺序依次执行,不允许任何并发操作。
但是由于完全串行的执行方式,可能会导致严重的性能问题,特别是在高并发情况下。
--选择合适的事务隔离级别
读未提交:适用于高并发的读写操作,但可能会导致脏读问题
读已提交:平衡了并发性能和数据一致性,是许多应用场景的默认选择
可重复读:对于复杂查询和数据一致性要求较高的场景,可以选择
串行化:在高并发和数据一致性要求极高的场景使用,需要注意性能开销
9、MySql面试题、
--innodb和myisam的区别?
innodb支持事务处理、行级锁定和外键,适用于需要高并发和事务处理的场景,
myisam不支持事务和行级锁定,但是读取速度快,适用于查询密集型的场景。
--JOIN操作
join操作通常用于结合两个或者多个数据库表的行,类型包括inner join只返回两表匹配的行
left join返回左表所有行及右表匹配的行 right join返回右表所有行及左表匹配的行
--如何优化mysql的查询?
选择合适的索引、避免在where子句中使用函数 选择合适的数据类型 使用limit语句减少数据量 避免全表扫面 合理设计表的结构
--什么是索引,它是如何提高查询性能的?
索引是数据库的对象,可以提高数据检索的速度,类似于书的目录,使数据库能够快速定位并检索数据,而不必扫描整个表,索引在大量数据处理的时候可以显著提高查询性能。
--mysql主键和唯一键的区别?
主键使表中用于唯一标识每条记录的列或者列的组合 一个表只能有一个主键 且主键列的值必须是唯一的 不允许位null
唯一键也确保列的值唯一,但一个表可以有多个唯一键 并且唯一键的列可以包含null值
--什么是视图?
视图是基于sql语句的结果集的可视化结果,像一个虚拟表,包含了一个或者多个表中获取的数据,视图的优点是可以简化复杂的sql查询、保护数据、更改数据格式和表示等
--什么是外键?
外键是一种数据库约束,用于建立两个表之间的关系,在一个表中的外键会指向另一个表的主键,外键的主要作用是维护跨表的数据完整性,确保参照完整性。
--如何处理死锁呢?
处理死锁的常用方法:
1、最小化事务大小和持续时间:通过减少事务范围和减少它们持有锁的时间来降低死锁的风险
2、避免多个事务同时修改相同的数据行:设计应用逻辑,以减少事务之间的交互
3、索引的合理使用:确保查询是高效的,并且尽可能使用索引 可以减少锁的范围
4、检测和日志记录:使用SHOW ENGINE INNODB STATUS命令检查死锁日志,分析和调整应用逻辑
--在MySql中,UTF-8和UTF8MB4的区别是什么?
两者都是字符编码,UTF8MB4是UTF8的超集,支持存储4个字节的Unicode字符,这意味UTF8MB4可以存储更多的字符,可以存储特殊的表情。
--Mysql优化器是什么?如何工作?
优化器是数据库管理系统中的一个组件,负责分析和选择执行SQL查询的最佳方式,考虑不同的执行计划,优化器的选择基于统计信息和数据库的内部算法。
--Mysql的全文索引?
允许对文本数据进行快速的全文搜索操作
--Mysql的ACID属性。
A:原子性 确保事务中的所有操作要么全部完成,要么全部不完成。
C:一致性 确保事务的执行结果总是从数据库从一个有效状态转换成另一个有效的状态
I:隔离性 确保并发执行的事务彼此独立
D:持久性 确保一旦事务提交 其结果就永久保存在数据库中
--mysql的常见的性能瓶颈有哪些 如何优化?
磁盘IO 网络延迟 查询效率(使用索引 优化复杂查询 避免全表扫描) 锁竞争
--mysql中聚簇索引和非聚簇索引的区别?
聚集索引:表数据按照索引的顺序物理存储,每个表只能有一个聚簇索引,通常是主键
非聚集索引:索引存储的是数据的逻辑顺序,而数据本身则存储在表的其他地方,非聚簇索引可以有多个
--mysql的B树索引和哈希索引有什么区别?
B树索引和哈希索引的区别主要在于两者的结构和应用场景:
B树索引:适用于全键值,键值范围和键值前缀的查找,在mysql中,大多数索引是B树索引
哈希索引:适合精确匹配查找
--mysql的having和where的区别?
都用于过滤数据
where子句 用于过滤行数据 发生在数据分组之前 不能与聚合函数在一起使用
having子句 用于过滤分组后的数据集 通常和聚合函数一起使用
--mysql处理和优化长时间的查询?
查询分析:使用EXPLAIN或其他工具分析查询执行计划
索引优化:确保查询使用了正确的索引
查询重写:修改复杂的查修你逻辑 简化或者分解查询
资源调整:增加内存分配 调整mysql配置以优化配置
硬件升级
--mysql如何处理null值 对性能有什么影响?
null表示缺失或者未知的数据
索引通常不包括null值,因此包含null值的列上的查询可能不会应用到索引
在比较操作中,任何与null值的比较都会返回null即未知,这可能会影响查询逻辑
使用适当的函数COALESCE或者IS NULL来处理NULL值
--mysql如何处理和分析死锁
启用死锁日志 通过SHOW ENGINE INNODBS STATUS 查看死锁信息
分析死锁日志来理解造成死锁的事务和操作
修改应用逻辑 减少长时间持有锁的操作 或者改变事务的锁定顺序
浙公网安备 33010602011771号