Bohr-L Bohr-L
首页
技术
常见面试题
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

刘博

I'm a slow walker, But I never walk backwards.
首页
技术
常见面试题
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 数据处理与存储类

  • Spring 生态类

  • 缓存问题类

  • 多线程类

  • JVM 类

  • MySQL 类

    • MySQL 为什么一定要有一个主键
      • MySQL 中的 RR 隔离级别,到底有没有解决幻读问题
      • MySQL 的行级锁到底锁的是什么东西?
      • 存储 MD5 值应该用 VARCHAR 还是用 CHAR?
      • 数据库的三范式是什么?
      • 说说 InnoDB 与 MyISAM 的区别
      • drop、truncate、delete 的区别
      • 聊一聊数据库事务机制
      • 聊一聊 MySQL 中的关联查询
      • 事务隔离级别有哪些?MySQL 的默认隔离级别是什么
      • 分库分表之后,id 主键如何处理?
      • 说说在 MySQL 中一条查询 SQL 是如何执行的?
      • 讲解下 DDL、DML、DCL
      • 存储过程和触发器的作用
      • MySQL 如何行转列和列转行
      • 如何查看 SQL 的执行计划
      • union 和 unionAll 的区别
      • having 和 where 的区别
      • 常见的索引原则
      • MySQL 中的 IN 和 EXISTS 子句有什么区别?
      • MySQL 如何处理 NULL 值,对性能有什么影响?
      • 如何在 MySQL 中处理和避免全表扫描?
      • MySQL 中的表空间是什么,它的作用是什么?
      • 在 MySQL 中,如何优化 ORDER BY 查询?
    • Java 8 + 特性类

    • 其他技术类

    • 常见面试题
    • MySQL 类
    刘博
    2025-12-28
    目录

    MySQL 为什么一定要有一个主键

    MySQL 中 “建议为表设置主键”(InnoDB 表默认会生成隐藏主键,若未显式定义),核心原因是 “确保数据唯一性、提升查询效率、维护索引结构、保证事务一致性”,具体如下:

    # 1. 确保数据唯一性,避免重复记录

    主键(Primary Key)的核心特性是 “非空(NOT NULL)且唯一(UNIQUE)”,可唯一标识表中的每一条记录,避免业务上的重复数据:

    • 示例:用户表(user)用id作为主键,确保不会出现两个id=1的用户记录;
    • 若未设置主键,可能因业务逻辑漏洞插入重复数据(如重复的用户手机号),且难以定位和删除重复记录。

    # 2. 提升查询效率,优化索引性能

    • InnoDB 的索引结构依赖主键:InnoDB 采用 “聚簇索引(Clustered Index)” 结构,聚簇索引的叶子节点存储完整的行数据;而聚簇索引默认基于主键构建(若未显式定义主键,InnoDB 会选择第一个非空唯一索引作为聚簇索引;若也没有,会生成隐藏的row_id作为聚簇索引);
    • 主键查询效率最高:基于主键的查询(如SELECT * FROM user WHERE id=100)可直接通过聚簇索引定位到行数据,无需回表(非主键索引的叶子节点存储主键值,查询时需先查非主键索引,再查聚簇索引,即 “回表”);
    • 避免全表扫描:若表无主键且无其他索引,查询数据时需全表扫描(遍历所有行),效率极低(尤其是百万级以上数据)。

    # 3. 维护表间关联关系,确保数据一致性

    在多表关联场景中,主键作为 “外键(Foreign Key)” 的引用基础,确保关联数据的完整性:

    • 示例:订单表(order)的user_id字段作为外键,引用用户表(user)的主键id;
    • 通过外键约束(如ON DELETE CASCADE),可确保:若删除用户表中的某条记录,订单表中关联的订单记录自动删除,避免 “孤儿数据”(订单表中user_id指向不存在的用户id)。

    # 4. 支持事务和 MVCC,保证数据版本一致性

    InnoDB 的事务隔离和 MVCC(多版本并发控制)机制依赖主键:

    • MVCC 通过 “undo 日志” 维护数据的多版本,undo 日志中记录行数据的主键,用于定位和恢复历史版本;
    • 若表无主键,InnoDB 需用隐藏row_id维护 MVCC,增加内存和磁盘开销,且可能影响事务性能。

    # 5. 避免 InnoDB 生成隐藏主键,减少性能开销

    若未显式定义主键,InnoDB 会:

    1. 检查表中是否有非空唯一索引,若有,将其作为聚簇索引;
    2. 若没有,生成隐藏的row_id(6 字节,自增)作为聚簇索引;
    • 隐藏row_id的缺点:
      • 不可见,无法通过SELECT查询,不利于问题排查;
      • row_id仅在当前表自增,若表数据被迁移或合并,可能出现重复(主键应全局唯一);
      • 基于row_id的查询效率低于显式主键(如业务上常用user_id查询,而非隐藏row_id)。

    上次更新: 12/30/2025
    JVM 如何处理异常?try-catch-finally 结构在字节码层面是如何实现的?
    MySQL 中的 RR 隔离级别,到底有没有解决幻读问题

    ← JVM 如何处理异常?try-catch-finally 结构在字节码层面是如何实现的? MySQL 中的 RR 隔离级别,到底有没有解决幻读问题→

    最近更新
    01
    CPU 使用率较高排查和解决
    12-29
    02
    JVM OOM 问题如何排查和解决
    12-29
    03
    接口防刷怎么实现?
    12-29
    更多文章>
    Theme by Vdoing | Copyright © 2025-2026 Bohr-L's note
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式