年中面试第二部分,打算简单的讲一下 MySQL 面试中碰到的问题,本文不做太多的延伸,只针对题目。

MySQL

常见的数据库存储引擎有哪些,有什么区别

这是个老生常谈的问题,常见的就是 innoDB 和 MyIsam,面试官想问的通常就是这两个

  1. innoDB 支持事务,MyIsam 不支持
  2. innoDB 是聚集索引,使用 B+Tree 作为索引结构,主键和数据在一起,在数据查询的时候,非主键索引会先索引到主键,然后再查询导数据。MyIsam 是非聚集索引,索引与文件是分开的,索引保存的是到数据文件的指针
  3. innoDB 支持行级锁,MyIsam 支持表级锁
  4. innoDB 必须要有主键,MyIsam 可以没有
  5. MyIsam 用一个变量保存了表的行数,在执行 count(*) 的时候可以 O(1) 地返回,但是不能有 where,innoDB 则会扫描全表

索引数据结构为什么选择B+树,和hash的优劣

hash索引的特性是 k-v 结构,在单行查找时有很高的效率,但是范围查找地成本就会很高。而且不可避免地会发生 hash 冲突问题,这时候需要引入链表来协助存储。

其实还有一种有序数组的方案,在查询时可以利用二分法等查找方案极大地降低时间复杂度,但是在插入地时候又暴露出了很大的问题,插入新数据,需要把后面所有数据后移。

相较之下,B+ 树的很多特性就很优秀

  1. 多路平衡树,左节点小于右节点,父节点小于右节点,查找效率高
  2. 为了解决树太高,访问磁盘过高,B+ 树是一个多叉树
  3. 查询以及更新的时间复杂度都为 O(log(N))
  4. 扩展到分库分表的时候,可以使用雪花算法做一个 id 生成器,保证 id 有序增长,不会发生页分裂

事务隔离等级有哪些

  1. 读未提交(RU):直接读取最新的记录值,不同事务之间会发生脏读、幻读、不可重复读的问题
  2. 读已提交(RC):在每条SQL执行开始,会先创建一个视图/更新视图,不同事务之间会出现不可重复读、幻读问题
  3. 可重复读(RR):开始事务之前创建一个视图,整个事务持续期间共享这一个视图,不同事务之间会出现幻读问题
  4. 序列化(S):读加读锁,写加写锁,不会出现问题

MySQL是怎么保证事务的几个特性的

  1. redo log重做日志用来保证事务的持久性
  2. undo log回滚日志保证事务的原子性
  3. undo log+redo log保证事务的一致性
  4. 锁(共享、排他)用来保证事务的隔离性

行锁表锁间隙锁排它锁

共享锁(S):读锁。允许一个事务去读取一行,阻止其他事务修改这一行。如果事务 A 对数据对象 L 加了 S 锁,事务 B 只能读 L,不能修改 L,只可以加 S 锁,不可以加 X 锁,直到 L上的 S 锁都释放之后,才可以加 X 锁。

排它锁(X):写锁。允许获取 X 锁的事务对数据进行修改,组织其他事务对操作的数据进行加锁( X 锁与 S 锁均不可以)。

update、insert、delete 都会自动给涉及到的数据加上排它锁,但是普通的 select 没有锁机制。

间隙锁(Next-Key):当我们使用范围条件查询,并请求共享锁或者排它锁的时候,innoDB 会给符合条件的记录加锁,对于键值在范围内,但是并不存在的记录区间,会加上间隙锁。

redo log、undo log、bin log 的记录时间

以一个具体事务举例 A=1,B=2 -> A=3,B=4

  1. 事务开始
  2. 查询 A 这一行记录,如果不在内存里,去磁盘读如内存
  3. 将 A=1 记录 undo log
  4. A 设置为3
  5. 更新进内存
  6. 写入 redo log
  7. 查询 B…
  8. 写 binlog
  9. 提交 commit

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

2020年年中面试-Redis 上一篇
2020年年中面试-Go 语言 下一篇

 目录