万丈金数服务端开发二面面经(已OC)
《面试题目》
- 聊简历上的项目,梳理核心业务的调用链路
- Git 是怎么做版本管理、记录所有版本变更的?如果让你来实现,你会怎么设计?
- .git 文件夹里面有什么内容,有没有看过?
- MySQL 的事务隔离级别有哪些?
- MySQL 默认的可重复读隔离级别,模拟一下读的整个过程
- 如果要开启一个新事务怎么办?如果自己写一套事务框架会怎么实现?
- 如果发生嵌套事务,要求事务隔离,怎么保证事务之间不会互相影响?
- 子事务如果抛异常回滚,会不会影响父事务?
- Java 异常的两大分类是什么?为什么要区分这两种异常?
- MySQL 的字符串类型有哪些?char 和 varchar 怎么选择?varchar 和 text 怎么取舍?
- 项目的数据库中有用过 JSON 类型的字段吗?
- 二分查找在实际项目中的什么场景会用到?
- 数据库索引的机制是什么,B+树的结构是怎样的?
- varchar 这类变长类型,数据库是怎么管理它们的存储结构的?
- AI 工具用得多吗?聊聊 AI 使用情况和项目中 AI 生成代码的比例
《参考解析》
- MySQL 事务隔离级别:从低到高依次是读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read,InnoDB 默认级别)、串行化(Serializable)。可重复读级别下,同一事务内多次读取同一份数据结果保持一致,这是通过 MVCC(多版本并发控制)在事务开始时生成一份 ReadView 实现的;同时 InnoDB 还通过间隙锁(Gap Lock)弥补了标准可重复读下可能出现的幻读问题。
- 嵌套事务/子事务回滚:MySQL 原生不支持真正的嵌套事务,通常借助 Savepoint 模拟——子事务对应一个保存点,子事务异常时只回滚到该保存点,不影响父事务已提交的其他操作;如果不使用 Savepoint,子事务的回滚可能会连带影响整个外层事务,因此在设计上需要显式声明事务传播行为(类似 Spring 的
REQUIRES_NEW或NESTED)来控制隔离范围。 - Java 异常两大分类:受检异常(Checked Exception,编译期强制要求处理或声明抛出,如
IOException)和非受检异常(Unchecked Exception,即RuntimeException及其子类,运行时才会暴露)。这样区分的目的是把”可预见、调用方应该主动处理的外部异常”和”编程错误导致的异常”分开:前者强制处理保证程序健壮性,后者不强制捕获,避免过度的 try-catch 掩盖真正的 bug。 - char / varchar / text 选型:char 是定长类型,存储时会用空格补齐到指定长度,适合长度固定的短字段(如状态码、md5 值),读写性能更好;varchar 是变长类型,按实际内容长度存储(加长度前缀),适合长度不固定的字段,但有长度上限(受行大小限制,最大 65535 字节,且要和其他字段共享该上限);text 用于存储更大的文本内容,不能设置默认值,通常只能建前缀索引,字段本身也不会存储在行内(可能存到溢出页)。
- B+树索引结构:B+树的所有数据都存储在叶子节点(聚簇索引的叶子节点存整行数据,二级索引的叶子节点存主键值),非叶子节点只存索引键作为导航,不存数据,因此非叶子节点可以容纳更多索引项、树的层高更低,磁盘 IO 次数更少;同时叶子节点之间通过双向链表相连,天然适合范围查询和排序查询。这也是 MySQL 选择 B+树而不是普通 B树或哈希索引的核心原因。