MySQL篇面试题(2026最新)

0 阅读1小时+
  1. 有了关系型数据库,为什么还需要NOSQL?

NOSQL数据库无需提前设计表结构,数据可以根据需要自由地存储和组织,而且相对于关系型数据库,NOSQL高效灵活,非常适合那些复杂、高变化、高并发量的场景中。

一句话总结

需要事务和数据一致性,用关系型数据库;需要高并发和灵活存储,用 NoSQL,二者协同,构成完整的存储架构

  1. MySQL的数据存储一定是基于硬盘的吗?

MySQL 不是一定基于硬盘存储,而是内存 + 硬盘的双层存储架构

  1. 运行时:核心数据全在 内存(Buffer Pool 缓冲池),所有增删改查都先操作内存,内存是高性能的核心,读写速度极快;
  2. 持久化:最终数据必在硬盘(.ibd 数据文件 + redo log/binlog 日志),内存数据会异步刷到硬盘,硬盘是数据安全的核心,保证宕机不丢数据;
  3. 核心逻辑: 内存 后硬盘,性能靠内存,安全靠硬盘。
  1. InnoDB和MyISAM有什么区别?

InnoDB 和 MyISAM 是 MySQL 两大存储引擎,核心区别:

  1. InnoDB 支持事务、行级锁、外键,崩溃可恢复,适合业务表、订单表等核心业务;
  2. MyISAM 不支持事务和外键,是表级锁,并发差,仅适合读多写少的静态表,比如日志表;
  3. 现在项目开发统一用 InnoDB,MySQL 默认也是 InnoDB。
  1. char和varchar的区别?

  1. char 是定长字符串,浪费空间、存取快、自动去尾部空格,长度 0-255;
  2. varchar 是变长字符串,节省空间、存取稍慢、保留空格,长度 0-65535;
  3. 定长用 char,变长用 varchar。
  1. MySQL 5.x和8.0有什么区别?

MySQL8.0 对比 5.x 是重大升级,核心区别主要有这几点:

  1. 8.0 默认存储引擎 InnoDB,移除 MyISAM;字符集默认 utf8mb4,支持 emoji,5.x 是 utf8 不支持;
  2. 8.0 自增主键持久化,重启不重置,解决主键重复问题,密码加密更安全;
  3. 8.0 原生高性能支持 JSON,新增窗口函数,移除查询缓存,性能和并发更优;
  4. 8.0 的锁机制、事务优化更好,整体安全性和功能完整性远超 5.x 版本。
  1. 什么是数据库范式,为什么要反范式?

数据库范式是设计规范,核心三大范式,逐级减少数据冗余、保证数据完整性,避免数据异常;

  1. 1NF:字段不可拆分(原子性);2NF:消除部分依赖;3NF:消除传递依赖;
  2. 反范式是刻意违反范式,适当加冗余字段、减少多表关联,目的是提升查询性能;

核心原则:范式保证数据整洁,反范式提升查询效率,项目中适度结合使用。

  1. 为什么大厂不建议使用多表join?

大厂不建议多表 JOIN 是核心性能规范,核心原因有 3 点:

  1. 多表 JOIN 会产生笛卡尔积,数据量越大查询越慢,百万级数据下极易产生慢查询;
  2. 占用数据库大量资源,降低数据库并发能力,而数据库是系统性能的核心瓶颈;
  3. 分库分表场景下多表 JOIN 完全失效,且表结构耦合度高,不利于业务扩展。

解决方案:优先单表查询,业务层做数据关联,牺牲少量业务层性能,保障数据库高可用和高并发。

  1. 说一说MySQL一条SQL语句的执行过程?

MySQL 执行一条 SQL 的核心流程,分5 步核心环节,顺序固定:

  1. 连接器:建立连接,校验账号密码和权限;
  2. 查询缓存: 如果是 mysql8.0 之前的还有查询缓存步骤,如果满足了直接返回
  3. 分析器:词法 + 语法分析,校验 SQL 是否合法;
  4. 优化器:制定最优执行计划,选索引、定执行路径;
  5. 执行器:校验权限,调用存储引擎执行 SQL;
  6. 存储引擎:读取磁盘数据(走索引 / 全表扫描),返回结果,最终整理后给到客户端。

关键补充:MySQL8.0 移除查询缓存,整体是服务层 + 存储引擎层的分层架构。

  1. InnoDB支持哪几种行格式?

InnoDB 存储引擎一共支持4 种行格式,核心记常用的 3 种即可:

  1. Redundant:早期兼容格式,冗余、空间利用率低,已淘汰;
  2. Compact:基础紧凑格式,MySQL5.6 及之前默认,兼顾性能和空间;
  3. Dynamic:MySQL5.7/8.0默认行格式(核心),优化大字段存储,空间利用率最优,项目主流;
  4. Compressed:动态格式的压缩版,节省磁盘空间,读多写少场景用。

核心考点:行格式决定数据物理存储方式,Dynamic 是现在的默认和首选。

  1. 什么是数据库事务机制?

数据库事务是一组不可分割的 SQL 执行集合,核心规则:要么全部执行成功,要么全部失败回滚。

事务的核心是四大特性,简称ACID:

  1. 原子性:不可拆分,全成或全败;
  2. 一致性:执行前后数据合法、无异常;
  3. 隔离性:多事务并发互不干扰;
  4. 持久性:提交后数据永久生效,不会丢失。

补充考点:MySQL 默认事务隔离级别是可重复读,解决脏读和不可重复读,事务是 InnoDB 引擎独有特性,MyISAM 不支持事务。

✔️ 追问 1:事务的四大特性里,哪个是核心?

答:原子性是基础,一致性是最终目的,隔离性和持久性都是为了保障一致性,所有特性的核心目标都是保证数据库数据准确无误。

✔️ 追问 2:InnoDB 和 MyISAM 对事务的支持有区别吗?

答:有!InnoDB 引擎完全支持事务的 ACID 四大特性,这也是 InnoDB 成为 MySQL 默认引擎的核心原因;MyISAM 引擎完全不支持事务,没有原子性和回滚机制,修改数据时崩溃会导致数据丢失或不一致,现在基本淘汰。

✔️ 追问 3:事务提交后,为什么数据不会丢失?(体现技术深度)

答:因为 InnoDB 会生成两类日志保障持久性:① redo log 重做日志:事务执行时实时写入,记录数据修改的物理日志,提交后持久化到磁盘;② binlog 归档日志:记录 SQL 的逻辑日志。即使数据库崩溃,重启后会通过 redo log 恢复已提交的事务数据,保证持久性。

  1. InnoDB的一次更新事务过程是怎么样的?

InnoDB 执行一次 update 更新事务,是加锁→内存修改→日志写入→提交事务→异步刷盘的完整流程,全程带事务 ACID 特性:

  1. 开启事务,执行 update,InnoDB 对更新行加行级排他锁,防止并发修改;
  2. 加载数据到内存缓冲区,完成数据修改,生成内存脏页;
  3. 执行两阶段提交:先写 redo log(prepare 状态)→ 再写 binlog → 最后 redo log 改为 commit 状态;
  4. 提交事务,释放行锁,本次更新具备持久性;
  5. 后台线程异步将内存脏页刷到磁盘,完成最终持久化。

✔️ 核心考点:更新事务的核心是两阶段提交 + redo log 保证数据不丢,行级锁保证并发安全,所有更新都是事务内操作,要么全成功要么全回滚。

✔️ 追问 1:为什么一定要有两阶段提交?少一步行不行?

答:绝对不行!两阶段提交是为了解决 redo log 和 binlog 的日志一致性问题。如果先写 redo log 直接 commit,再写 binlog,binlog 写入失败的话,数据库重启后 redo log 恢复了数据,但 binlog 没有记录,主从同步会丢数据;如果先写 binlog,再写 redo log,redo log 写入失败,数据库重启后数据丢失,但 binlog 有记录,数据不一致。两阶段提交能保证:要么两个日志都写成功,要么都失败,彻底避免日志不一致导致的数据问题。

✔️ 追问 2:update 更新失败 / 执行 rollback 回滚,会发生什么?

答:① 如果更新失败(比如主键冲突、约束校验失败),直接执行 rollback 回滚;② 回滚时,不会刷盘,直接通过undo log 回滚日志,将内存中修改的脏页恢复成修改前的原始数据;③ redo log 和 binlog 不会写入有效数据,行锁直接释放;④ 回滚后,数据库恢复到事务执行前的状态,完美保证事务的原子性。

✔️ 追问 3:update 的行锁什么时候加?什么时候释放?(高频中的高频)

答:行锁是在执行 update 查询到目标行的时候就加上,不是 commit 的时候加;行锁是在事务 commit 提交 或 rollback 回滚之后才释放。这个机制的核心是:保证整个事务期间,被修改的行不会被其他事务操作,彻底避免并发修改冲突。

  1. 什么是脏读、幻读、不可重复读?

脏读、不可重复读、幻读是事务并发时的 3 种读异常,都是隔离性不足导致的:

  1. 脏读:读了其他事务未提交的脏数据;
  2. 不可重复读:同事务内,同查询多次读同一条数据,结果不一样(被修改提交);
  3. 幻读:同事务内,同范围查询多次读,数据条数不一样(被新增 / 删除提交)。

核心区别:不可重复读是改数据,幻读是增删数据;MySQL 默认的可重复读级别,解决脏读和不可重复读,规避幻读。

  1. MySQL中的事务隔离级别?

MySQL 有4 种事务隔离级别,按从低到高排序:读未提交、读已提交、可重复读、串行化,核心考点如下:

  1. 读未提交:有脏读、不可重复读、幻读,性能最高,隔离最差;
  2. 读已提交:解决脏读,仍有后两种异常,是 Oracle 默认级别;
  3. 可重复读:MySQL默认级别,解决脏读、不可重复读,InnoDB 规避幻读,最优平衡;
  4. 串行化:解决所有问题,事务串行执行,性能极差。

核心总结:隔离级别越高,问题越少,并发越差,日常开发用 MySQL 默认的可重复读即可。

  1. InnoDB如何解决脏读、不可重复读和幻读的?

InnoDB 彻底解决脏读、不可重复读、幻读,核心是 可重复读 隔离级别 + MVCC ****多版本并发控制 + 锁机制 三者结合,核心答案一句话分点说清:

  1. 解决脏读:靠隔离级别 + MVCC,只读取其他事务已提交的数据版本,未提交的脏数据完全读不到;
  2. 解决不可重复读:靠可重复读级别 + MVCC,事务内生成一致性快照,全程读同一份数据版本,不会被其他事务的修改影响;
  3. 解决幻读:靠双层防护,普通查询用 MVCC 快照读规避,写操作加临键锁(行锁 + 间隙锁)锁住数据区间,禁止其他事务增删数据,彻底根治。

核心考点:MVCC 负责读的一致性,锁负责写的安全性,这是 InnoDB 的两大核心技术。

  1. MySQL 的 select * 会用到事务吗?

核心结论:

  1. 用 InnoDB 引擎时,select *一定会用到事务,是 MySQL 自动开启的隐式事务,自动完成开启和提交;
  2. 用 MyISAM 引擎则不会,因为它不支持事务。
  1. 为什么MySQL默认使用RR隔离级别?

MySQL 默认使用可重复读(RR) 隔离级别的核心原因有 3 点:

  1. RR 级别彻底解决脏读、不可重复读,InnoDB 通过 MVCC + 临键锁又规避了幻读,能解决全部三类读异常,隔离性拉满;
  2. RR 是隔离性和并发性能的最佳平衡点:并发性能和读已提交持平,隔离性远超其他级别,比串行化的性能好太多;
  3. 完美适配绝大多数业务场景,事务内查询结果一致,无额外开发成本,是综合最优解。

✔️ 核心总结:RR 的核心优势 = 顶级隔离性 + 高性能并发 + 零业务适配成本

  1. 为什么默认RR,大厂要改成RC?

  1. RR 的硬伤:RR 为解决幻读,会加临键锁(行锁 + 间隙锁),锁范围大,高并发下锁冲突、 死锁 多,并发写入性能差
  2. RC 的优势:RC 只有行级锁,无间隙锁,锁粒度极细,锁冲突极少,并发写入性能大幅提升,TPS 显著提高;
  3. 取舍合理:RC 的缺点是存在不可重复读,但这个问题在大厂业务中无实际风险,完全可接受;而 RR 解决的幻读,在大厂的分库分表架构中也无实际意义。

核心总结:大厂用无影响的隔离性妥协,换实打实的高并发性能和线上稳定性

  1. Innodb的RR到底有没有解决幻读?

核心回答:InnoDB 的 RR(可重复读)隔离级别在一定程度上解决了幻读问题。

  1. 从数据读取角度:通过 MVCC(多版本并发控制),在事务执行期间,读取的是事务开始时的快照数据,避免了普通查询时由于其他事务插入、删除数据而产生的幻读现象。
  2. 从数据写入角度:对于存在更新、删除操作的场景,InnoDB 使用间隙锁和临键锁,阻止其他事务在锁定区间内插入数据,防止幻读。

避坑点

  1. 不能简单说 RR 完全解决了幻读,要区分查询和写操作场景。
  2. 解释时需清晰说明 MVCC 和间隙锁、临键锁的作用,避免概念混淆。
  1. 如何理解MVCC?

核心回答:MVCC 即多版本并发控制,是一种用于数据库并发控制的技术,旨在提高并发性能。

• 实现原理:在数据库每行记录后添加隐藏字段,记录创建版本号和删除版本号。事务开启时会有唯一事务版本号,读数据时根据可见性规则,通过版本号判断哪些数据版本对当前事务可见。

• 作用场景及优势:在读写并发场景下,读操作基于版本号读取快照数据,无需加锁,避免读写冲突,提高系统并发性能,如在 InnoDB 的可重复读和读已提交隔离级别中应用。

避坑点:

• 不要将 MVCC 与锁机制混淆,MVCC 主要解决读写并发问题,锁侧重解决写写冲突。

• 明确不同隔离级别下 MVCC 的可见性规则差异,避免回答笼统

  1. 当前读和快照读有什么区别?

核心回答:当前读和快照读是数据库中不同的读取方式。

  1. 定义及特点:

    1. 快照读:读取的是记录的快照版本,使用 MVCC 来避免加锁,提高并发性能。普通的 SELECT 语句在 RR、RC 隔离级别下就是快照读。
    2. 当前读:读取的是记录的最新版本,读取时会对记录加锁,保证数据的一致性。如 SELECT...FOR UPDATE、UPDATE、DELETE 等语句。
  2. 适用场景:快照读适用于读多写少、对实时性要求不高的场景;当前读适用于对数据实时性要求高、有写操作的场景。

避坑点

  1. 不能简单认为快照读就一定没加锁,要根据隔离级别判断。
  2. 解释时要结合不同的 SQL 语句,避免只说概念不举例。
  1. 介绍下InnoDB的锁机制?

核心回答:InnoDB 锁机制丰富,保障数据并发访问的一致性。

  1. 锁类型:

    1. 行级锁:细粒度锁,开销大、加锁慢、冲突概率低。包括共享锁(S 锁),可并发读;排他锁(X 锁),读写互斥。
    2. 表级锁:粗粒度锁,开销小、加锁快、冲突概率高。意向锁表示事务对表中某些行加了行级锁,用于协调行级锁和表级锁。
    3. 间隙锁:在可重复读隔离级别下,防止幻读,锁定索引记录间隙,而非记录本身。
  2. 锁算法:有 Record Lock(记录锁)、Gap Lock(间隙锁)、Next-Key Lock(临键锁,记录锁和间隙锁组合)。

避坑点

  1. 区分不同锁类型的特点和适用场景,如行锁和表锁的选择。
  2. 理解间隙锁和临键锁的概念,避免在可重复读隔离级别下对幻读问题解释不清。
  1. MySQL的行级锁锁的到底是什么?

核心回答:MySQL 行级锁主要锁的是索引记录和索引间隙。

  1. 索引记录:当通过索引条件进行数据操作时,行级锁会锁定符合条件的索引记录。例如执行 UPDATE 语句按索引查找更新,会对命中的索引记录加锁,阻止其他事务对这些记录的并发修改。
  2. 索引间隙:在可重复读隔离级别下,为防止幻读,会使用间隙锁或临键锁锁定索引记录之间的间隙。这样其他事务无法在这些间隙插入新记录。

避坑点

  1. 不要误以为行级锁只锁数据行,而忽略索引间隙。
  2. 理解行级锁基于索引工作,若查询未用索引,可能会退化为表级锁。
  1. 什么是排他锁和共享锁?

核心回答:排他锁和共享锁是数据库中用于并发控制的两种锁类型。

  1. 排他锁(X 锁):也叫写锁,加锁后,其他事务不能再加任何类型的锁,即读写都被禁止。像在执行 UPDATE、DELETE、INSERT 语句时,会自动加排他锁,保证数据修改的完整性和一致性。
  2. 共享锁(S 锁):又称读锁,事务加共享锁后,其他事务也能加共享锁,但不能加排他锁。多个事务可以同时读同一资源,提高了并发读取的效率,如 SELECT...LOCK IN SHARE MODE 语句会加共享锁。

避坑点

  1. 明确两种锁的兼容性,避免混淆读写操作限制。
  2. 解释时结合具体 SQL 语句,防止只阐述概念。
  1. 什么是意向锁?

核心回答:意向锁是 InnoDB 存储引擎为协调行级锁和表级锁而引入的一种表级锁。

  1. 作用:表明事务对表中的某些行持有行级锁。当一个事务要对表加表级锁时,可通过检查意向锁来快速判断表中是否有行被加锁,避免逐行检查,提高加锁效率。
  2. 类型:分为意向共享锁(IS)和意向排他锁(IX)。事务对某行加共享锁前,需先对表加 IS 锁;加排他锁前,需先对表加 IX 锁。

避坑点

  1. 别将意向锁和行级锁、表级锁的功能混淆,它主要起协调作用。
  2. 理解意向锁是表级锁,在解释时强调其与行级锁的关联。
  1. 乐观锁与悲观锁如何实现?

核心回答:乐观锁和悲观锁是两种不同的并发控制策略,实现方式各异:

  1. 乐观锁:假设数据一般不会发生冲突,不提前加锁。实现上,常使用版本号机制或 CAS 算法。版本号机制是在表中加版本号字段,每次更新时版本号加 1,更新时检查版本号是否一致;CAS(比较并交换)是在内存中比较值,若相等就更新,否则重试。
  2. 悲观锁:认为数据很可能冲突,操作前先加锁。数据库中,使用 SELECT... FOR UPDATE 语句,会对查询记录加排他锁;Java 中,使用 synchronized 和 Lock 接口实现。

避坑点

  1. 乐观锁要注意 ABA 问题,可通过带版本号的 CAS 解决。
  2. 悲观锁要避免死锁,合理设计加锁顺序。
  3. 清晰区分两种锁的适用场景,如读多写少用乐观锁,写多读少用悲观锁。
  1. Innodb加索引,这个时候会锁表吗?

核心回答:InnoDB 加索引时是否锁表取决于 MySQL 的版本和加索引的方式:

  1. MySQL 5.5 及之前版本:添加索引会锁表,期间表不能进行读写操作,因为采用的是重建表的方式,会复制一份原表数据,在复制过程中对原表加锁。
  2. MySQL 5.6 及之后版本:支持 Online DDL,添加索引时一般不会锁表。它可以在不阻塞读写操作的情况下完成索引添加,但在某些特殊情况,如空间不足时,可能会退化为锁表操作。

避坑点

  1. 要明确不同版本的差异,避免错误回答。
  2. 说明 Online DDL 有特殊情况会锁表,不能绝对说不锁表。
  1. InnoDB中的索引类型?

核心回答:InnoDB 支持多种索引类型,核心的有以下几种:

  1. 主键索引:基于主键建立的索引,要求主键唯一且非空,叶子节点存储整行数据,是聚簇索引。
  2. 二级索引:也叫辅助索引,叶子节点存储主键值,通过主键值再回表查询整行数据。
  3. 唯一索引:索引列的值必须唯一,但允许有空值,可加快查询速度并保证数据唯一性。
  4. 全文索引:用于全文搜索,对文本内容进行分词处理,适合在文本字段较多的表中使用。
  5. 空间索引:针对空间数据类型(如几何图形)建立的索引,用于高效处理空间查询。

避坑点

  1. 区分聚簇索引(主键索引)和非聚簇索引(二级索引)的结构和查询方式。
  2. 说明唯一索引和主键索引的区别,唯一索引可有空值。
  3. 不要遗漏全文索引和空间索引的适用场景。
  1. InnoDB为什么使用B+树实现索引?

核心回答:InnoDB 使用 B + 树实现索引,主要基于以下优势:

  1. 磁盘读写性能好:B + 树的高度通常较低,减少了磁盘 I/O 次数。每个节点存储多个键值,降低了树的高度,提高查找效率。
  2. 范围查询高效:B + 树的叶子节点形成有序链表,对于范围查询,只需遍历链表即可,无需像 B 树那样频繁回溯。
  3. 数据存储集中:叶子节点包含所有数据,非叶子节点仅用于索引,提高了空间利用率。

避坑点

  1. 要准确阐述 B + 树和 B 树的区别,突出 B + 树在范围查询和磁盘读写上的优势。
  2. 不能简单说 B + 树好,要结合 InnoDB 的应用场景说明其适用性。
  1. MySQL是如何保证唯一性索引的唯一性的?

核心回答:MySQL 通过以下方式保证唯一性索引的唯一性:

  1. 插入检查:在插入新记录时,数据库会检查唯一性索引列的值是否已经存在于索引中。若存在,则插入失败,并返回错误信息。
  2. 事务支持:InnoDB 存储引擎支持事务,在事务中插入或更新数据时,会对相关索引加锁,防止并发操作破坏唯一性。
  3. 索引结构:B + 树索引结构使得查找特定值的效率很高,能快速定位是否存在重复值。

避坑点

  1. 不要忽略事务和锁机制在保证唯一性中的作用。
  2. 明确是在插入和更新操作时进行唯一性检查,而非查询。
  1. 什么是聚簇索引和非聚簇索引?

核心回答

  • 聚簇索引:索引键值的逻辑顺序和表中相应行的物理存储顺序一致,数据和索引存放在一起。在 InnoDB 中,主键索引就是聚簇索引,叶子节点存储整行数据。
  • 非聚簇索引:也叫二级索引,索引键值的逻辑顺序和表的物理存储顺序无关,叶子节点存储的是主键值,查询时需通过主键值回表查询数据。

避坑点

  1. 清晰区分两者数据存放位置,避免混淆。
  2. 说明在 InnoDB 中主键和聚簇索引的关系,以及非聚簇索引回表查询的流程。
  1. 什么是回表,怎么减少回表的次数?

核心回答

  • 回表是指在使用非聚簇索引查询时,先从非聚簇索引中找到主键值,再根据主键值到聚簇索引中获取完整数据的过程。

  • 减少回表次数的方法:

    • 使用覆盖索引,让查询的字段都包含在索引中,直接从索引获取数据,无需回表。
    • 建立合适的联合索引,将多个查询字段组合成一个索引。
    • 优化查询语句,只查询必要的字段,避免查询过多无用列。

避坑点

  1. 准确理解回表是基于非聚簇索引和聚簇索引的交互,不能混淆概念。
  2. 创建索引要考虑成本,避免过度索引导致性能下降。
  3. 优化查询语句时,要结合业务需求,确保不遗漏关键信息。
  1. 什么是索引覆盖、索引下推?

核心回答

  • 索引覆盖:指查询语句只需要从索引中就能获取所需的全部数据,无需回表到聚簇索引中查询。例如,查询的字段都包含在联合索引里,直接从该索引获取数据,提高查询效率。
  • 索引下推:在使用索引进行数据查询时,MySQL 5.6 之后引入的优化策略。在索引遍历过程中,对索引中包含的字段先进行条件过滤,减少回表次数。比如在联合索引中,对索引里能判断的条件先筛选,再决定是否回表。

避坑点

  1. 清楚区分索引覆盖是数据直接从索引获取,而索引下推是在索引遍历阶段提前过滤。
  2. 理解索引覆盖和索引下推都是为减少回表,提高查询性能,但原理不同。
  3. 运用时要根据实际表结构和查询需求,避免错误使用导致性能未提升。
  1. 设计索引的时候有哪些原则(考虑哪些因素)?

核心回答:设计索引需考虑以下原则和因素:

  1. 查询频率:为经常用于查询条件、排序或分组的字段建索引。
  2. 字段区分度:选择区分度高的字段,区分度越高索引效果越好,如身份证号。
  3. 避免冗余:已有 (a,b) 联合索引,无需单独为 a 建索引。
  4. 索引顺序:联合索引中,将区分度高、查询频繁的字段放在前面。
  5. 索引数量:适量创建索引,过多索引会增加写操作成本和占用空间。

避坑点

  1. 不能只看字段使用频率,忽略区分度。
  2. 注意联合索引字段顺序,顺序错误影响索引效率。
  3. 防止索引数量过多导致数据库性能下降,并非越多越好。
  1. MySQL索引一定遵循最左前缀匹配吗?

核心回答:MySQL 索引通常遵循最左前缀匹配原则,但并非绝对。

  • 最左前缀匹配:对于联合索引(a, b, c),查询条件从索引最左列开始,且连续,才能使用索引。如 WHERE a = 1 AND b = 2 可使用该索引,WHERE b = 2 AND c = 3 则无法使用。

  • 特殊情况

    • 索引下推优化:MySQL 5.6 及之后版本,在索引遍历过程中会对索引中包含的字段先进行条件过滤,即使不满足最左前缀,部分场景也能利用索引。

避坑点

  1. 不能认为所有情况下都严格遵循最左前缀,要考虑数据库版本和优化策略。
  2. 分析查询性能时,不能仅依据最左前缀判断索引是否可用,需结合执行计划。
  1. MySQL的主键一定是自增的吗?

核心回答:MySQL 的主键不一定是自增的。主键选择是灵活的,可选用任意数据类型。不过通常单独创建自增字段作主键,具有以下优点:

  1. 索引大小更小:自增特性让新数据插入到索引末尾,减少数据页分裂与相关 IO 操作,使索引更小,查询更快。
  2. 索引与插入顺序一致:保证索引和插入顺序相同,减少新数据插入时索引重新排序,提升插入速度。
  3. 安全性高:避免主键重复,确保数据完整性与唯一性。
  4. 减少页分裂与内存碎片。

避坑点

  1. 不能绝对认为自增主键适用于所有场景,如分布式系统中自增主键可能存在问题。
  2. 要明确主键选择需结合业务需求,不能仅因自增主键优点就盲目使用。
  1. uuid和自增id做主键哪个好,为什么?

核心回答:自增主键和 UUID 作为主键各有优缺点:

  1. 自增主键

    1. 优点:顺序插入,索引性能好,占用空间小,生成简单。
    2. 缺点:跨库合并数据困难,大量插入时可能有性能瓶颈,安全性低。
  2. UUID

    1. 优点:全局唯一,适合分布式系统,数据合并方便。
    2. 缺点:无序,影响索引性能,占用空间大,生成和存储成本高。

避坑点

  1. 不能只看优点忽视缺点,比如不能只看到 UUID 全局唯一,而忽略其对索引性能的影响。
  2. 根据具体业务场景选择,如分布式系统较适合 UUID,而单数据库简单业务用自增主键更合适。
  1. order by 是怎么实现的?

核心回答ORDER BY排序方式由优化器选择,主要有索引排序和filesort排序两种:

  1. 索引排序:因索引天然有序,若使用索引排序效率高。但是否采用由优化器基于成本评估决定,以下情况走索引概率高:查询字段和order by字段组成联合索引且查询符合最左前缀匹配、有少量limit、虽不遵循最左前缀匹配但前导列用常量查询。
  2. filesort 排序:无法使用或优化器认为索引排序效率低时采用。MySQL 为每个线程分配sort_buffer用于排序,大小由sort_buffer_size控制。若排序数据量小于该值,在内存排序;反之则用磁盘临时文件辅助排序。max_length_for_sort_data决定排序算法,单行长度超过该值采用rowid排序,否则用全字段排序。全字段排序是将查询所有字段放sort_buffer,按排序字段排序后直接返回结果集。

避坑点

  1. 不能认为只要使用索引字段排序就一定走索引排序,要考虑多种因素,结果并非 100% 确定。
  2. 注意合理设置sort_buffer_sizemax_length_for_sort_data参数,否则可能导致排序性能下降。
  3. 避免在排序字段较长或数据量较大时盲目使用全字段排序,可能占用过多内存。
  1. count(1)、count(*) 与 count(列名) 的区别

核心回答:三者在使用和性能上有差异:

  1. count(1) :固定传入常量 1,数据库不关心表记录内容,统计行数。性能与count(*)接近,在早期数据库版本中对特定表引擎可能有性能优势。
  2. count(*) : SQL92 标准统计函数,统计所有记录行数,包含NULL值。优化器会对其做优化,性能较好。
  3. count (列名) : 统计指定列非NULL值的行数。若列允许NULL值,则不统计NULL值所在行;若列被声明为NOT NULL,统计结果同count(*)。性能与列是否有索引有关,有索引性能较好。

避坑点

  1. 不要认为count(1)总比count(*)快,现代数据库多数情况两者性能差异不大。
  2. 使用count(列名)时,要清楚列是否允许NULL值,避免统计结果偏差。
  1. limit 0,100和limit 10000000,100一样吗?

核心回答LIMIT 0, 100LIMIT 10000000, 100 不一样,这涉及 MySQL 深度分页问题。

  1. 原理差异:MySQL 的 LIMIT m, n 先读取 m + n 条记录,抛弃前 m 条,返回后 n 条。LIMIT 0, 100 从第 1 行开始取 100 条,无需跳过记录;而 LIMIT 10000000, 100 要跳过 10000000 条记录,先读 10000100 条,性能差。
  2. 优化方法:若查询行数明确,用 LIMIT 比查出全量结果再丢弃好。MySQL 针对 LIMIT 有优化,如仅查几行可能用索引;与 ORDER BY 组合时,找到 row_count 行后停止排序等。不过这些优化的前提是未使用 HAVING 语句。
  3. 注意事项ORDER BY 字段有重复值时,加 LIMIT 查询结果可能不稳定,可增加不会重复的字段(如 id)排序。

避坑点

  1. 避免在大数据量查询中使用大偏移量的 LIMIT,否则性能严重下降。
  2. ORDER BYLIMIT 时,考虑排序字段重复值对结果稳定性的影响。
  3. 理解 LIMIT 优化前提是未用 HAVING 语句,避免错误应用优化策略。
  1. binlog、redolog和undolog区别?

核心回答:binlog、redolog 和 undolog 是 MySQL 不同用途的日志,区别如下:

  1. 适用场景:binlog 用于全存储引擎的数据备份、恢复与复制;redolog 和 undolog 仅用于 InnoDB 引擎,前者保障崩溃恢复和持久化,后者用于事务回滚及 MVCC。
  2. 记录内容:binlog 记 DDL、DML 语句;redolog 记事务数据改动;undolog 记事务修改前的数据。
  3. 实现机制:binlog 按指定格式记录,有语句和行格式;redolog 循环写,崩溃时重执行记录;undolog 反向执行记录来撤销修改。

避坑点

  1. 别把不同日志使用场景弄混,如用 redolog 备份数据。
  2. 要清楚 redolog 和 undolog 只适用于 InnoDB。
  3. 理解记录内容时,别混淆修改前和修改后数据的记录日志。
  1. 用了索引还是很慢,可能是什么原因?

核心回答:使用索引查询仍慢,可能有以下原因:

  1. 选错索引:当 SQL 有多个索引可选时,MySQL 优化器可能选错,导致查询变慢。
  2. 数据分布不均:数据分布不均会使部分索引节点数据量过大,部分过小,降低查询性能。
  3. SQL 语句问题:未优化的 SQL 语句,如使用SELECT *、多表join等,会影响查询性能。
  4. 数据库设计不合理:表结构设计不佳,会使查询需扫描大量数据,影响性能。
  5. 系统硬件或网络问题:系统硬件性能不足或网络环境差,也会导致查询变慢。

避坑点

  1. 不要盲目认为走了索引就一定快,要考虑索引选择是否正确。
  2. 设计数据库和编写 SQL 时,要注重优化,避免常见的性能问题。
  3. 排查问题时,不要忽略系统硬件和网络环境的影响。
  1. SQL执行计划分析的时候,要关注哪些信息?

核心回答:分析 SQL 执行计划时,需关注以下关键信息:

  1. id:表示查询中操作的执行顺序,id 值越大越先执行,相同则按顺序执行。
  2. select_type:区分查询类型,如简单查询、子查询、联合查询等,不同类型执行效率有差异。
  3. table:显示操作涉及的表名。
  4. type:反映查询的访问类型,从好到差有 systemconsteq_refrefrangeindexALL 等,尽量保证 typeref 及以上。
  5. possible_keys:显示可能使用的索引。
  6. key:实际使用的索引。
  7. rows:MySQL 预估执行查询所需扫描的行数,越少越好。
  8. Extra:包含额外重要信息,如 Using filesort(需额外排序操作)、Using temporary(使用临时表),应尽量避免。

避坑点

  1. 不能仅关注单一指标,要综合分析各信息。
  2. 对于 Extra 中的特殊信息要重视,理解其对性能的影响。
  3. 不要盲目依赖 MySQL 预估的 rows 数,它只是估算值。
  1. 如何优化一个大规模的数据库系统?

核心回答:优化大规模数据库系统可从多方面入手:

  1. 硬件优化:升级硬件,如用 SSD 硬盘减少 I/O 延迟,增加内存缓存数据,使用高速网络或同机房部署减少网络延迟。
  2. 数据库设计:简化表结构,避免过度多表 join,合理冗余数据;定期归档旧数据。
  3. 查询优化:优化 SQL 语句,避免复杂子查询、多表 JOIN 和深度分页;分析查询计划并优化。
  4. 索引优化:对常查询和排序列建索引,避免过多索引,尽量用覆盖索引。
  5. 缓存机制:用 Redis 缓存频繁查询结果,对常访问且变化少的对象本地缓存。
  6. 负载均衡:采用读写分离,主库写、从库读;使用数据库集群分散负载。
  7. 分区和分片:分库提升连接数和吞吐量,分表降低单表数据量。
  8. 数据备份和恢复:采用备份、恢复及数据同步技术保障数据安全和可用。
  9. 性能监控和调优:用监控和分析工具定期监控调优。

避坑点

  1. 硬件升级要基于实际需求,避免过度投资。
  2. 设计索引时,要结合查询频率和效率,避免盲目创建。
  3. 引入缓存要考虑一致性和维护成本,分库分表要规划好数据分布。
  4. 不能忽视数据备份恢复和性能监控调优,它们保障系统稳定运行。
  1. MySQL只操作同一条记录,也会发生死锁吗?

核心回答:MySQL 只操作同一条记录也可能发生死锁。死锁本质是两个或多个事务相互等待对方释放锁。在只操作同一条记录时,以下情况可能导致死锁:

  1. 不同锁请求顺序:若两个事务以不同顺序对同一条记录加不同类型锁(如先加共享锁再加排他锁),可能形成循环等待。
  2. 事务并发修改:多个事务同时对同一条记录进行修改,在更新过程中锁的持有和等待可能造成死锁。

避坑点

  1. 不要认为操作同一条记录就不会死锁,要关注锁的请求顺序和事务并发情况。
  2. 分析死锁时,查看事务日志和锁信息,准确找出死锁原因。
  1. 数据库死锁如何解决?

核心回答:解决数据库死锁可从预防、检测和处理三方面着手:

  1. 预防死锁

    1. 固定事务中锁资源的获取顺序,避免循环等待。
    2. 减少事务持有锁的时长,比如降低事务内的操作复杂度。
    3. 尽量使用排他锁的替代方案,如乐观锁。
  2. 检测死锁:数据库系统一般自带死锁检测机制,可定期检查事务间的依赖关系。

  3. 处理死锁:当检测到死锁,数据库会选择一个事务作为牺牲品进行回滚,释放其持有的锁,让其他事务继续执行。

避坑点

  1. 不要过度依赖死锁检测和处理,预防死锁才是关键。
  2. 使用乐观锁要考虑版本控制和并发冲突。
  3. 配置死锁检测参数时,要平衡检测频率和性能开销。
  1. 索引失效的问题如何排查?

核心回答:排查索引失效可按以下步骤进行:

  1. 查看执行计划:使用 EXPLAIN 关键字分析 SQL 执行计划,关注type字段,如值为ALL可能表示全表扫描,索引失效;同时查看key字段,若未使用预期索引则有问题。
  2. 检查 SQL 语句:查看是否存在违背索引使用规则的情况,例如对索引列进行函数运算、隐式类型转换、使用!=NOT IN等。
  3. 检查索引本身:确认索引是否存在损坏,可以通过数据库管理工具或命令查看索引的状态;也需考虑索引是否因数据分布不均匀,导致优化器不选择该索引。
  4. 分析数据量和统计信息:数据量变化大时,统计信息可能不准确,影响优化器决策。可使用ANALYZE TABLE更新统计信息后再测试。

避坑点

  1. 不能仅依据执行计划判断索引失效,要结合 SQL 逻辑和业务场景。
  2. 注意隐式类型转换,在编写 SQL 时尽量保证数据类型一致。
  3. 更新统计信息可能会有一定性能开销,要选择合适时机操作。
  1. 如何进行SQL调优?

核心回答:SQL 调优可从多方面入手:

  1. 索引优化:分析查询语句,为经常作为过滤条件、排序或连接条件的列创建合适索引,避免在索引列上使用函数、避免隐式类型转换等导致索引失效的操作。
  2. 查询语句优化:简化查询逻辑,避免子查询嵌套过深;合理使用连接类型(如内连接、左连接);避免使用SELECT *,只选择需要的列。
  3. 数据库配置优化:根据服务器硬件资源,调整数据库的内存分配、缓存大小等参数,如调整 MySQL 的innodb_buffer_pool_size
  4. 表结构优化:合理设计表结构,如拆分大表、避免数据冗余;使用合适的数据类型以减少存储空间和提高查询效率。

避坑点

  1. 不要盲目创建索引,过多索引会增加写操作的开销和占用更多存储空间。
  2. 调优时要逐步进行,每次调整后进行性能测试,避免多个调整相互影响难以定位。
  3. 注意数据库版本差异,不同版本的配置参数和优化方法可能有所不同。
  1. 慢SQL的问题如何排查?

核心回答:排查慢 SQL 可按以下步骤:

  1. 日志记录:开启数据库的慢查询日志,设置合理的时间阈值(如 MySQL 的long_query_time),记录执行时间超过阈值的 SQL。
  2. 使用工具分析:利用数据库自带的性能分析工具,如 MySQL 的EXPLAIN,查看 SQL 的执行计划,分析是否全表扫描、索引使用情况等。
  3. 查看系统资源:监控数据库服务器的 CPU、内存、磁盘 I/O 等资源使用情况,判断是否因资源瓶颈导致 SQL 执行慢。
  4. 分析业务逻辑:检查 SQL 语句本身是否存在问题,如是否有复杂嵌套子查询、是否有不必要的排序和分组等。

避坑点

  1. 慢查询日志的时间阈值设置要合理,避免记录过多或过少信息。
  2. 不能仅依据EXPLAIN结果判断,还需结合实际业务场景和数据情况。
  3. 排查时要全面,不能只关注 SQL 本身而忽略服务器资源问题。
  1. MySQL主从复制的过程

核心回答:MySQL 主从复制主要有 3 个步骤:

  1. 二进制日志 记录:主库将变更记录到二进制日志(Binlog),在事务提交时写入。
  2. 二进制日志 传输:从库的 I/O 线程连接主库,请求主库发送 Binlog 更新,主库的 Binlog 转储线程读取 Binlog 并发送给从库,从库将其写入中继日志(Relay Log)。
  3. 中继日志重放:从库的 SQL 线程读取中继日志,将其中的 SQL 语句重放执行,使从库与主库数据一致。

避坑点

  1. 不要混淆不同线程的作用,注意 I/O 线程负责接收 Binlog,SQL 线程负责重放。
  2. 要考虑主从延迟问题,如主从复制延迟可能导致数据不一致,可通过监控工具及时发现。
  3. 需确保主从库的 Binlog 格式一致,避免复制异
  1. 介绍一下InnoDB的数据页,和B+树的关系是什么?

核心回答:核心知识点:InnoDB 数据页是存储数据的基本单位,B + 树是 InnoDB 索引和数据组织的结构,二者紧密相关。分点说明:

  1. InnoDB 数据页:是 InnoDB 存储引擎管理数据的最小物理单位,大小默认 16KB,包含数据、页头、页尾等部分,可存储记录、索引项等。
  2. 与 B + 树的关系:B + 树的每个节点对应一个数据页。叶子节点存储实际的数据记录,非叶子节点存储索引键和指向下一层数据页的指针,通过页内偏移量快速定位记录。

避坑点

  1. 不要误认为数据页只存储数据,它也存储索引等信息。
  2. 明确 B + 树节点和数据页的对应关系,避免混淆二者概念。
  1. MySQL的驱动表是什么?MySQL怎么选的?

核心回答:核心知识点:驱动表是多表连接查询中最先被处理的表,MySQL 会根据查询条件、表大小等因素选择。分点说明:

  1. 驱动表定义:在多表连接查询里,驱动表的每一行会与其他表进行匹配,驱动表的选择影响查询效率。

  2. 选择方式

    1. 若有 JOIN 条件,通常选择过滤后数据量小的表作为驱动表,可减少匹配次数。
    2. 当有 WHERE 子句时,优先选择 WHERE 条件过滤性强的表作为驱动表。
    3. 若没有过滤条件,小表通常作为驱动表。

避坑点

  1. 不要简单认为总是小表作驱动表,需结合过滤条件判断。
  2. 可通过 EXPLAIN 语句分析查询计划,确认 MySQL 选择的驱动表是否合理。
  1. MySQL执行大事务会存在什么问题?

核心回答:MySQL 执行大事务存在诸多问题,主要体现于资源、性能、并发和数据层面:

  1. 资源方面:长时间占用数据库连接,导致其他事务获取不到连接,降低系统吞吐量;产生大量日志,可能撑满磁盘空间。
  2. 性能方面:回滚操作因涉及大量数据而耗时久,影响数据库可用性;主从同步时,主库执行时间长,造成备库同步延迟。
  3. 并发方面:大量写操作会锁定很多数据,引发严重的锁竞争,使其他事务等待时间变长。
  4. 数据方面:影响 MVCC 的正常运行,旧版本数据无法及时清理;还会使查询难以使用覆盖索引,降低查询效率。

避坑点

  1. 不能只关注业务功能实现,而忽略大事务对数据库性能和稳定性的影响。
  2. 拆分大事务时,要确保业务逻辑的完整性和数据的一致性。
  1. SQL中PK、UK、CK、FK、DF是什么意思?

核心回答:这些是 SQL 中常见约束的缩写,用于保证数据的完整性和一致性:

  1. PK( Primary Key 主键 :唯一标识表中每一行记录,不允许为空且值唯一,一个表只能有一个主键。
  2. UK(Unique Key,唯一键) :要求字段值唯一,但可以为 NULL,一个表可定义多个唯一键。
  3. CK(Check Constraint,检查约束) :指定某字段值的取值范围或格式要求,确保输入数据符合条件。
  4. FK( Foreign Key 外键 :建立两个表之间的关联,一个表的外键指向另一个表的主键,保证数据引用的完整性。
  5. DF (Default,默认值) :为字段指定默认值,当插入记录未提供该字段值时,使用默认值。

避坑点

  1. 区分 PK 和 UK,PK 不允许 NULL 且表中唯一,UK 可以有 NULL 值且可多个。
  2. 定义 CK 时,确保检查条件合理,避免过于严格或宽松。
  3. 使用 FK 时,注意主表和从表数据的删除和更新操作规则,避免引用出错。
  1. 什么是buffer pool?

核心回答:Buffer Pool 即缓冲池,是 InnoDB 存储引擎用于缓存数据和索引的内存区域。

  • 工作原理:数据库读取数据时,先检查 Buffer Pool 有无该数据,有则直接返回,无则从磁盘读入并缓存;写入数据时,先更新 Buffer Pool,再在合适时机刷新到磁盘。
  • 作用:减少磁盘 I/O,提高数据库读写性能,因为内存访问速度远快于磁盘。

避坑点

  1. 合理配置 Buffer Pool 大小,过大会影响系统其他组件性能,过小则无法充分发挥其缓存作用。
  2. 要注意脏页刷新机制,避免大量脏页同时刷新影响性能。
  1. buffer pool的读写过程是怎么样的?

核心回答:Buffer Pool 的读写过程如下:

读过程

  1. 当有读请求时,先在 Buffer Pool 中查找所需数据页。
  2. 若找到,即命中缓存,直接从内存返回数据,快速完成读取。
  3. 若未找到,产生缺页中断,从磁盘读取该数据页到 Buffer Pool,再将数据返回。

写过程

  1. 写数据时,直接在 Buffer Pool 中修改对应的数据页,将其标记为脏页。
  2. 后台线程会在合适时机(如空闲时、达到一定阈值等)将脏页刷新到磁盘,保证数据持久化。

避坑点

  1. 读时注意缓存命中率,低命中率可能是 Buffer Pool 大小设置不合理或数据访问模式特殊导致。
  2. 写时要关注脏页刷新机制,避免大量脏页同时刷新造成磁盘 I/O 高峰,影响性能。
  1. 什么是InnoDB的页分裂和页合并

核心回答:页分裂和页合并是 InnoDB 存储引擎在管理数据页时的重要机制。

  • 页分裂:当向已满的数据页插入新记录,且该页无法容纳时,InnoDB 会创建一个新的数据页,将原页部分记录移动到新页,以保证记录有序存储。这通常发生在 B + 树索引节点上,会增加索引层级和维护成本。
  • 页合并:当数据页中记录数量过少(低于某个阈值)时,InnoDB 会将该页与相邻页合并,释放磁盘空间,减少索引层级,提升查询性能。

避坑点

  1. 频繁页分裂会导致索引结构不稳定、性能下降,可通过合理设置页填充因子避免。
  2. 页合并阈值设置不当,可能导致频繁合并或合并不及时,影响空间利用和性能。
  1. MySQL自增主键用完了会怎么样?

核心回答:若 MySQL 自增主键用完,不同数据类型情况不同:

  1. TINYINT、SMALLINT 等小范围类型:达到上限后再插入会报 “Out of range value” 错误,插入失败。
  2. INT 类型:达到2^32 - 1后,继续插入会报相同错误,插入失败。
  3. BIGINT 类型:理论上限2^64 - 1,极难达到,若达到也会插入失败。

避坑点

  1. 设计表时要根据业务预估数据量,合理选择自增主键的数据类型,避免过早用完。
  2. 若可能达到上限,可考虑使用 UUID 等其他方式作为主键。
  1. 执行计划中,key有值,还是很慢怎么办?

核心回答:执行计划中key有值且type = index,很多人认为走了索引,但实际可能是全索引扫描,效率提升有限。出现这种情况大概率是未遵守最左前缀匹配原则导致索引失效,可从以下方面解决:

  1. 调整查询语句:检查 SQL 语句,让查询条件尽量符合最左前缀匹配原则,确保索引能有效使用。
  2. 修改索引:根据业务需求和查询语句,创建更合适的索引,保证索引能覆盖查询条件。

避坑点

  1. 不能仅依据key有值和type = index就认定是常规意义的走索引,要仔细分析Extra列信息。
  2. 排查索引失效问题时,重点关注最左前缀匹配原则的遵守情况。
  1. 数据库乐观锁的过程中,完全没有加任何锁吗?

核心回答:数据库乐观锁过程并非完全无锁。虽未显式加锁也未用数据库锁机制,但它基于update语句实现,数据库更新时会根据where条件对索引添加行级锁(可能还有间隙锁或临键锁)。

乐观锁相比悲观锁的意义在于:它通过 CAS 方式做并发校验,更新前无需提前加锁,仅在更新瞬间加短暂锁;而悲观锁需提前使用select for update加锁,锁时长更长。

避坑点

  1. 避免认为乐观锁完全无锁,要清楚更新操作中会存在隐含锁。
  2. 解释乐观锁优势时,要明确与悲观锁在加锁时机和锁时长上的对比差异。
  1. MySQL的binlog有几种格式

核心回答:MySQL 的 binlog 有 3 种格式:

  1. STATEMENT(语句级):记录 SQL 语句,优点是日志量小、节省空间、易于理解;缺点是部分函数(如UUID())在复制时可能产生不一致。
  2. ROW(行级):记录每行数据的变化,能准确复制数据变更,解决了 STATEMENT 的复制一致性问题,但日志量大。
  3. MIXED(混合级):结合了前两者,MySQL 根据语句特性自动选择合适格式记录。

避坑点

  1. 不要混淆不同格式的优缺点,如不能认为 STATEMENT 格式一定比 ROW 格式好。
  2. 选择 binlog 格式时,要考虑业务场景对复制一致性和日志量的要求。
  1. MySQL的并行复制原理

核心回答:MySQL 并行复制旨在提升主从复制效率,降低主从延迟,不同版本原理有别:

  1. MySQL 5.6:基于库的并行复制,不同数据库的事务可并行在从库回放,同一库事务仍串行。如主库有 db1、db2,db1 事务和 db2 事务可并行复制。
  2. MySQL 5.7:组提交并行复制,若事务在主库能并行提交,从库也可并行回放。依据是事务在主库提交顺序和组信息,只要事务在主库属同一组提交,从库就可并行执行。
  3. MySQL 8.0:增强组提交并行复制,通过更细粒度判断事务间依赖关系,并行度更高,进一步提升复制效率。

避坑点

  1. 要清楚不同版本并行复制原理差异,结合实际使用版本作答。
  2. 并非所有场景并行复制都适用,如事务间依赖强,并行复制效果可能不佳。
  3. 并行复制配置不当可能导致数据不一致,需谨慎设置参数。
  1. MySQL的深度分页如何优化

核心回答:MySQL 深度分页性能问题源于查询需扫描大量前置记录,可从四方面优化:

  1. 子查询与 JOIN 优化:子查询先获取限定条件下目标区域主键 id,主查询借 id 取完整行数据。如SELECT c1, c2, cn... FROM table INNER JOIN (SELECT id FROM table WHERE name = "xx" ORDER BY id LIMIT 1000000, 10) AS subquery ON table.id = subquery.id,有索引时子查询无需回表。
  2. 子查询和 ID 过滤优化:子查询获取分页起始参考点,基于 ID 做范围查询。如SELECT c1, c2, cn... FROM table WHERE name = "xx" AND id >= (SELECT id FROM table WHERE name = "xx" ORDER BY id LIMIT 1000000, 1) ORDER BY id LIMIT 10,但要求 ID 自增。
  3. 记录上一个 ID:记住上一页最大 ID,下一页按id > max_id_in_last_page查询,提前预估分页条件可提升性能。
  4. 使用搜索引擎:文本搜索可用 Elasticsearch 优化,不过 ES 也有深度分页问题,只是影响较小。

避坑点

  1. 采用子查询和 ID 过滤优化时,要保证 ID 是自增的,否则会影响效果。
  2. 用搜索引擎优化时,要清楚 ES 也存在一定深度分页问题,不能完全依赖。
  3. 选择优化方式需结合具体业务场景和数据特点。
  1. 什么是数据库的主从延迟,如何解决?

核心回答:数据库主从延迟指主从数据库复制时,从服务器数据与主服务器数据存在时间差。常见原因有:

  1. 网络延迟:主从节点间网络不佳导致复制延迟。
  2. 从节点性能问题:硬件资源不足,难处理复制事件。
  3. 复制线程不够:线程少使数据回放慢。
  4. 大事务:长事务执行慢,在从节点重放也慢。

解决办法如下:

  1. 优化网络:保证主从节点网络稳定,尽量同城或同单元部署。
  2. 提高从服务器性能:增加 CPU、内存和磁盘等硬件资源。
  3. 并行复制:利用 MySQL 并行复制能力,提升效率、降低延迟。
  4. 避免大事务:减少长事务,防止从节点重放缓慢。

避坑点

  1. 优化网络时,要综合考虑成本和实际网络环境,并非所有场景都适合同城或同单元部署。
  2. 提升从服务器性能时,要合理评估硬件资源需求,避免过度配置造成浪费。
  3. 采用并行复制时,要了解不同并行复制方式的适用场景和限制。
  4. 避免大事务时,要结合业务需求,不能盲目拆分事务影响业务逻辑。
  1. 什么是事务的2阶段提交?

核心回答:MySQL 事务的 2 阶段提交是保证 binlog 和 redolog 一致性的手段,过程分三步:

  1. Prepare 阶段:SQL 执行成功,生成 redolog 并写入磁盘,处于 prepare 状态。
  2. BinLog 持久化:将 binlog 内存日志写入磁盘。
  3. Commit:在执行引擎内部执行事务操作,写入 redolog,处于 Commit 阶段。

引入 2 阶段提交是为避免单写 redo log 或 binlog 失败导致主备库数据不一致。通过 2 阶段提交,不同崩溃情况处理如下:

  1. 一阶段提交后崩溃(redolog prepare 状态),回滚事务,主备一致。
  2. 一阶段成功,写完 binlog 崩溃,检查 binlog 事务完整性,完整则提交,否则回滚。
  3. redolog 处于 commit 状态崩溃,处理同情况二。

判断 binlog 和 redolog 一致,是通过对比 redolog 中 prepare 状态记录的全局唯一 XID 和 binlog 结束位置的 XID,一致则认为逻辑上一致。

避坑点

  1. 要清晰区分 2 阶段提交各步骤的操作和顺序,不能混淆。
  2. 解释崩溃情况处理时,要准确说明判断和处理依据。
  3. 理解 XID 判断一致性的原理,不能简单认为只要有 XID 就一致,要强调两者一致才行。
  1. 介绍下MySQL 5.7中的组提交

核心回答:MySQL 5.7 中的组提交是优化技术,提升性能和事务处理效率。它将多个事务提交操作合并为批处理,减少磁盘 IO 和锁定开销。数据库数据变更涉及 binlog、redolog、undolog 写入,频繁写入触发磁盘操作,组提交可减少磁盘 IO 次数,将多事务修改一次性写入二进制日志。

组提交有两个配置参数:

  1. binlog_group_commit_sync_delay:延迟多久通过 fsync 刷盘持久化数据。
  2. binlog_group_commit_sync_no_delay_count:累积多少次操作后通过 fsync 刷盘持久化数据。二者是或关系,满足其一触发提交。

引入组提交后,两阶段提交有变化。fsync 操作延迟,等一组中多个事务都处于 Prepare 阶段后,进行一次组提交将日志持久化到磁盘。

避坑点

  1. 要明确组提交是为减少磁盘 IO,不能误解其目的。
  2. 理解两个配置参数是或关系,不能混淆逻辑。
  3. 解释组提交对两阶段提交的影响时,要突出 fsync 延迟这一关键变化。
  1. 什么是最左前缀匹配?为什么要遵守?

核心回答:最左前缀匹配指在 MySQL 查询中,利用索引最左边部分进行匹配。若创建组合索引(如 idx_col1_col2_col3 (col1, col2, col3)),查询条件为 col1、(col1, col2)、(col1, col2, col3) 或(col1, col3)时,可利用该索引;若查询条件不含 col1,则通常无法利用此索引。且最左前缀匹配与查询条件顺序无关,创建组合索引只是生成一棵按指定列依次排序的 B + 树。单个字段索引使用 like 模糊匹配时,“like 'ab%'” 可走索引,“'% bc'”“'b% c'” 不行。

遵循最左前缀匹配原则是因为 MySQL 的 InnoDB 引擎索引基于 B + 树实现,联合索引构建 B + 树时先按左边列排序,相同则按右边列排序。查询只有从最左边开始匹配,才能利用到该索引。

避坑点

  1. 不要误以为组合索引会生成多个独立索引,实际是一棵 B + 树。
  2. 清晰区分联合索引和单字段索引最左前缀匹配的情况,避免混淆。
  3. 解释遵循原则原因时,要紧扣 B + 树排序逻辑,不能表述不清。
  1. 为什么MySQL 8.0要取消查询缓存?

核心回答:MySQL 的查询缓存可在执行 SELECT 时缓存查询结果,后续相同查询可直接返回缓存结果,在特定环境能提升性能。但它存在诸多限制,如查询文本需字节级匹配、含非确定性函数或临时表的查询不缓存、表修改使缓存失效、部分存储引擎不支持等。

MySQL 8.0 取消查询缓存,主要因其缺点明显:

  1. 频繁失效:以表级别管理,表数据变化会清除相关所有查询缓存,降低效用。
  2. 内存开销:需大量内存存储查询文本和结果集,对大数据量数据库造成内存压力。
  3. 不一致性:数据更改后,缓存结果可能与实际不符,导致数据不一致。
  4. 查询分布不均匀:难以应对不均匀的查询分布,部分频繁查询更新缓存频繁,不频繁查询又难命中。

取消查询缓存有助于提高整体性能和可维护性。

避坑点

  1. 不能只强调查询缓存的优点,而忽略其缺点对取消决策的影响。
  2. 解释每个缺点时要准确清晰,如说明缓存失效是以表级别为单位。
  3. 理解取消查询缓存是综合考虑性能和可维护性的结果,避免片面解读。
  1. MyISAM 的索引结构是怎么样的,它存在的问题是什么?

核心回答:MyISAM 采用索引和数据分离的存储方式,索引文件和数据文件独立。其索引树叶子节点存储的是数据所在的地址,不支持聚簇索引概念,所有索引都是非聚簇索引。

基于此结构,MyISAM 存在的问题是:根据索引查询时需要先查到数据地址,再查询真正的数据,有两次查询过程,相比聚簇索引的数据检索效率较低。

和 InnoDB 最大不同在于,InnoDB 引入了聚簇索引,基于聚簇索引查询无需回表,叶子节点包含数据内容,可提高数据检索效率,尤其是主键检索。

避坑点

  1. 要准确理解并表述 MyISAM 索引结构中叶子节点存储的是数据地址,避免与 InnoDB 混淆。
  2. 解释查询过程时,清晰说明两次查询的步骤,不能模糊表述。
  3. 对比与 InnoDB 差异时,突出聚簇索引对数据检索效率的影响,不要遗漏重点。
  1. MySQL中like的模糊查询如何优化

核心回答:MySQL 中 like 模糊查询优化方法有:

  1. 合理使用通配符like 'abc%'可使用索引,避免%abc%%abc这样无法用索引的形式。
  2. 字段逆序:将需查询字段反转存入冗余列并建索引,查询用冗余列,但更新冗余列数据量大时耗时久且增大表空间。
  3. 虚拟列:MySQL 5.7.6 及以上版本,创建虚拟列并建索引,查询用虚拟列可走索引。虚拟列分 VIRTUAL 和 STORED,磁盘大时用 STORED 查询更快。还可用 union 合并不同 like 查询,用覆盖索引提升性能。
  4. 全文索引:适用于文本搜索,使用MATCH AGAINST替代 like,性能更好,但仅支持特定存储引擎(如 MyISAM、InnoDB)。

避坑点

  1. 采用字段逆序时,考虑数据更新耗时和表空间问题。
  2. 使用虚拟列要注意版本要求,根据磁盘情况选类型。
  3. 全文索引使用场景有限,要结合实际情况判断是否适用。
  1. 什么是MySQL的字典锁?

核心回答

  • 定义:MySQL 的字典锁(Metadata Locks,MDL)是用于保护数据库对象元数据的锁,确保在对表进行读写操作时,元数据不会被并发修改。
  • 作用机制:当对表执行 DML(如 SELECT、INSERT)操作时,会自动加共享 MDL 锁;执行 DDL(如 ALTER TABLE)操作时,会加排他 MDL 锁。共享锁之间兼容,共享锁和排他锁、排他锁之间互斥。
  • 影响:若有长事务持有共享 MDL 锁,此时执行 DDL 操作会被阻塞;反之,若 DDL 操作持有排他 MDL 锁,DML 操作也会被阻塞,可能导致性能问题。

避坑点

  1. 避免在长事务中进行频繁的 DML 操作,防止长时间占用共享 MDL 锁,影响 DDL 操作。
  2. 执行 DDL 操作前,先检查是否有长事务持有共享锁,可通过 SHOW ENGINE INNODB STATUS 等命令查看。
  3. 注意事务的隔离级别,不同隔离级别下 MDL 的行为可能有差异。
  1. 什么是OnlineDDL

核心回答

  • 定义:Online DDL(Online Data Definition Language)是指在不影响或最小化影响数据库正常业务的情况下,对数据库表的结构进行修改的技术。
  • 实现方式:不同数据库的实现有所不同,以 MySQL 为例,它在 5.6 版本引入了 Online DDL 功能,主要通过创建临时表、复制数据、重命名表等步骤实现。在操作过程中,会利用行锁来减少对正常业务的影响,支持并发的 DML 操作。
  • 优点:大大减少了数据库表结构修改时的停机时间,提高了系统的可用性和稳定性,降低了对业务的影响。
  • 缺点:可能会占用更多的系统资源,如磁盘 I/O、CPU 等;操作过程中可能会出现一些意外情况,如复制数据失败等。

使用例子

ALTER TABLE tbl_name RENAME INDEX old_index_name TO new_index_name, ALGORITHM=INPLACE, LOCK=NONE;

避坑点

  1. 在执行 Online DDL 前,要充分评估系统资源,避免因资源不足导致操作失败或影响业务性能。
  2. 操作前进行充分的测试,确保不会出现数据丢失或不一致的问题。
  3. 注意操作过程中的监控,及时处理可能出现的异常情况。
  1. 为什么不推荐使用外键?

核心回答

  • 性能影响:使用外键时,数据库在进行插入、更新、删除操作时需要额外检查外键约束,这会增加数据库的开销,降低操作性能。例如插入一条记录时,需要检查关联表中是否存在对应记录。
  • 维护复杂:当表结构发生变化,如修改表名、字段名时,外键的维护会变得复杂,可能需要修改外键定义,增加了维护成本。
  • 扩展性差:在分布式系统或微服务架构中,不同服务可能使用不同的数据库,外键难以跨数据库实现,不利于系统的扩展。
  • 死锁风险:外键约束可能导致死锁情况的发生,多个事务相互等待对方释放资源,影响系统的正常运行。

避坑点

  1. 不要只看到外键保证数据一致性的优点,而忽视其带来的性能和维护问题。
  2. 在设计数据库时,要综合考虑业务需求和系统架构,不能盲目使用外键。
  3. 若使用外键,要做好性能测试和监控,及时发现并解决潜在问题。
  1. 唯一索引和主键索引的区别?

核心回答

  • 唯一性:二者都保证唯一,但主键索引是特殊的唯一索引。
  • 是否可空:主键索引不可为 NULL,唯一索引可为 NULL。
  • 数量:一张表只能有一个主键索引,可创建多个唯一索引。
  • 索引结构:InnoDB 中,主键索引是聚簇索引,唯一索引通常是非聚簇索引,无主键时唯一索引可能被选为聚簇索引。
  • 是否回表:主键索引查询无需回表,唯一索引通常需回表。
  • 外键:主键可被引用为外键,唯一索引不行。

避坑点

  1. 别将主键索引和唯一索引的可空性、数量限制弄混。
  2. 理解唯一索引在特定情况下可成为聚簇索引,避免认知局限。
  3. 明确主键可被用作外键而唯一索引不行,答题时别遗漏该要点。
  1. 一个查询语句的执行顺序是怎么样的?

核心回答

  1. FROM 子句:从指定的表或视图中选取数据。
  2. JOIN 子句:如果有连接操作,按条件进行表连接。
  3. WHERE 子句:过滤不满足条件的行。
  4. GROUP BY 子句:对结果进行分组。
  5. HAVING 子句:对分组后的数据进行过滤。
  6. SELECT 子句:选择需要显示的列。
  7. ORDER BY 子句:对结果集进行排序。
  8. LIMIT 子句:限制返回的行数。

避坑点

  1. 不要将执行顺序与书写顺序混淆,书写顺序一般是 SELECT、FROM、WHERE 等,但执行顺序并非如此。
  2. 牢记每个子句的作用和执行先后,避免在分析查询语句时出现错误。
  1. truncate、delete、drop的区别?

核心回答

  1. 操作对象:TRUNCATE 和 DELETE 针对表数据,DROP 针对表结构和数据。
  2. 执行机制:TRUNCATE 直接删除数据页,速度快;DELETE 逐行删除,支持 WHERE 筛选;DROP 直接删除表定义。
  3. 事务处理:DELETE 可回滚;TRUNCATE 和 DROP 不可回滚。
  4. 日志记录:DELETE 记录详细日志;TRUNCATE 和 DROP 记录较少日志。

避坑点

  1. 用 TRUNCATE 和 DROP 前确认数据无需保留,因无法回滚。
  2. 区分使用场景,有条件删除用 DELETE,清空表用 TRUNCATE,删表用 DROP。