《JAVA八股真解》六、MySQL

#JAVA##JAVA面经##JAVA内推#

1. 数据库事务的 ACID 特性

ACID 是数据库事务的四大核心特性,确保数据的一致性、可靠性和完整性。

  1. 原子性(Atomicity)

    • 事务中的所有操作必须全部成功或全部失败。
    • 若任一操作失败,整个事务将回滚至初始状态,保证数据不被破坏。
  2. 一致性(Consistency)

    • 事务执行前后,数据库必须从一个一致状态转换到另一个一致状态。
    • 满足所有完整性约束,如主键唯一、外键关联等。
  3. 隔离性(Isolation)

    • 多个并发事务之间互不干扰,每个事务的操作与其他事务隔离。
    • 通过不同的隔离级别(读未提交、读已提交、可重复读、串行化)控制并发行为。
  4. 持久性(Durability)

    • 一旦事务提交成功,其对数据库的修改将永久保存。
    • 即使系统崩溃或重启,数据也不会丢失。

总结:ACID 特性共同保障了数据库事务的可靠性与一致性,是构建稳定系统的基石。

2. MySQL 存储引擎对比

特性 InnoDB MyISAM
事务支持 支持 不支持
行锁/表锁 行级锁 表级锁
外键约束 支持 不支持
崩溃恢复 支持(基于日志) 不支持
索引类型 聚集索引(主键即索引) 非聚集索引(独立存储)
MVCC支持 支持 不支持

说明

  • InnoDB:默认存储引擎,支持事务、行级锁、外键,适合高并发写入场景。
  • MyISAM:性能较高,但不支持事务和行锁,适用于只读或读多写少的场景。

选择建议

  • 一般项目优先使用 InnoDB。
  • 如果是纯查询系统且无需事务支持,可考虑 MyISAM。

3. 数据库事务隔离级别

MySQL 提供四种事务隔离级别,按严格程度递增:

隔离级别 读未提交(READ UNCOMMITTED) 读已提交(READ COMMITTED) 可重复读(REPEATABLE READ) 串行化(SERIALIZABLE)
脏读
不可重复读
幻读

解释

  • 脏读:读取未提交的数据。
  • 不可重复读:同一事务中多次读取结果不一致。
  • 幻读:新增或删除记录导致查询结果变化。

默认隔离级别:InnoDB 默认为 REPEATABLE READ,MyISAM 不支持事务,因此无此概念。

生产环境建议

  • 通常使用 READ COMMITTEDREPEATABLE READ
  • SERIALIZABLE 性能较差,仅在极端一致性要求下使用。

4. 索引的类型(种类)

MySQL 中常见的索引类型包括:

  • 普通索引(Normal Index)

    • 最基本的索引,允许重复值。
    • 用于加速查询,但无唯一性约束。
  • 唯一索引(Unique Index)

    • 索引列值必须唯一,不允许重复。
    • 常用于邮箱、手机号等字段。
  • 主键索引(Primary Key Index)

    • 一种特殊的唯一索引,不允许 NULL。
    • 每张表只能有一个主键索引。
  • 组合索引(Composite Index)

    • 在多个列上创建的索引,提高多条件查询效率。
    • 遵循“最左前缀原则”。
  • 全文索引(Full-text Index)

    • 用于文本内容的模糊搜索,如搜索引擎。
    • 仅支持 MyISAMInnoDB(5.6+)。
  • 空间索引(Spatial Index)

    • 用于地理空间数据,如经纬度坐标。

注意:合理使用索引可以大幅提升查询性能,但过多索引会影响写入性能。

5. [SQL] 索引失效的常见情况有哪些?

以下是可能导致索引失效的典型场景:

1. 使用函数或表达式

SELECT * FROM `stu` WHERE age + 10 > 30;

原因:对字段进行计算,无法直接匹配索引。

2. 使用隐式类型转换

SELECT * FROM `user` WHERE LEFT(date, 4) = '1998';

原因:字符串截取后比较,无法利用索引。

3. 使用 % 开头的 LIKE 查询

SELECT * FROM `name` WHERE name LIKE '%abc';

原因:前导通配符无法使用索引,需全表扫描。

4. 字符串与数字比较不匹配

CREATE TABLE t (a char(10));
INSERT INTO t VALUES ('1');
SELECT * FROM t WHERE a = 1; -- 不走索引

原因:隐式类型转换导致索引失效。

5. OR 条件混合使用

SELECT * FROM dept WHERE name='xxx' OR loc='xx' OR deptno = 45;

原因:若其中一个条件无法走索引,则整体可能不走索引。

6. 正则表达式不使用索引

SELECT * FROM user WHERE name REGEXP '^abc';

原因:正则表达式通常不走索引。

6. [MySQL] 索引底层原理

MySQL 的索引底层结构主要基于 B+ 树。

B+ 树特点:

  1. 非叶子节点只存储键值,不存储数据,减少磁盘 I/O。
  2. 所有叶子节点形成有序链表,便于范围查询。
  3. 叶子节点存储完整数据,支持快速定位。

优势

  • 支持高效范围查询。
  • 减少磁盘访问次数。
  • 适合大数据量场景。

7. 聚集索引与非聚集索引

InnoDB 存储引擎:

  • 聚集索引:主键即为聚集索引,数据物理存储顺序与主键一致。
  • 非聚集索引:额外创建的索引,指向聚集索引的主键值。

示例

-- 主键为 id,自动创建聚集索引
CREATE TABLE user (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    INDEX idx_name (name)
);

查询过程

  1. 通过 name 索引找到对应主键。
  2. 再通过主键查找完整数据(回表)。

优化建议

  • 尽量避免频繁回表,可通过覆盖索引优化。

8. MySQL 回表查询

当查询字段不在索引中时,需要先通过索引定位主键,再根据主键回表获取其他字段,称为“回表查询”。

示例

SELECT * FROM t WHERE name = 'lisi';

执行流程

  1. 使用 name 索引找到主键。
  2. 回表查询完整行数据。

优化方案

  • 创建覆盖索引,包含所需字段,避免回表。

9. MySQL 最左匹配原则

联合索引遵循“最左前缀”原则,查询条件必须从最左边开始匹配。

示例

CREATE INDEX idx_ab ON table(a, b);

以下查询可以使用索引:

SELECT * FROM table WHERE a = ?;
SELECT * FROM table WHERE a = ? AND b = ?;
SELECT * FROM table WHERE a = ? AND b = ? AND c = ?;

以下查询不能使用索引:

SELECT * FROM table WHERE b = ?;  -- 无法使用索引
SELECT * FROM table WHERE b = ? AND a = ?;  -- 无法使用索引

提示:合理设计联合索引顺序,提升查询效率。

10. count(*)count(1)count(字段) 的区别?

方法 是否统计空值 是否统计 NULL 是否统计所有行
count(*)
count(1)
count(字段)

详细说明

  • count(*):统计所有行数,最快,推荐使用。
  • count(1):效果同 count(*),但略慢(需计算常量)。
  • count(字段):只统计该字段非空的行数,若字段允许 NULL,则会忽略 NULL 值。
#java##JAVA##面经#

本专栏在精不在多,内容分为八股文、大厂真实面经,面试通过后将offer和面试题私发给我,可退还专栏的收益部分费用。欢迎大家共建专栏

全部评论

相关推荐

zbk1:学院本找嵌入式我觉得不太行,不要被培训班忽悠了,老老实实读个研吧。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务