头图

这些都是面试常见的问题,看看下面的问题你都能答得上来吗?

1.三大范式是什么,它们在数据库设计中的作用是什么?
2. 为什么在优化 SQL 查询时需要使用 EXPLAIN 命令?它能提供哪些关键信息?
3. 列举并简要说明常见的索引类型
4. 请列举索引失效的几种常见场景
5. 在什么情况下应该使用索引来优化查询?
6. 什么是数据库事务?它的基本特性是什么?
7. 事务的隔离级别是什么?它如何影响并发事务的执行?
8. 在数据库中,常见的并发问题有哪些?如何通过事务管理避免这些问题?
9. 什么是 MVCC(多版本并发控制)?
10. 为什么 MySQL 默认的可重复读隔离级别能够在很大程度上避免幻读?在高并发环境下,这两种解决方案的效果如何?
11. 数据库中的三种日志类型分别是什么?它们各自的作用是什么?

1. 三大范式是什么,它们在数据库设计中的作用是什么?

  • 1NF(第一范式) :第一范式要求一行中的每个单元格都应该有单一值,且不能出现重复列。也就是说表中一行中的列值是一个而不能是多个,也不能出现重复的列。
  • 2NF(第二范式) :在第一范式的基础上,第二范式要求每张表都应该有一个单一目的。也就是说这张表只能代表一种实体,而表中的每一列都应该用来描述那个实体。
  • 3NF(第三范式) :在第二范式的基础上,第三范式表示,表中的列不能派生自其他列。也就是说表中的列不能通过其他列得到。

    2. 为什么在优化 SQL 查询时需要使用 EXPLAIN 命令?它能提供哪些关键信息?

    explain 命令

  • 作用:作用于你写的sql语句,数据库会返回一个执行计划
  • 执行计划会有很多字段

    • type:指查询到所需行的方式,从好到坏的顺序:system>const>eq_ref>ref>range>index>ALL
    • possible_keys:候选的索引
    • key:实际使用的索引
    • rows:扫描行数
    • filtered:所需数据行占rows的比例

      3. 列举并简要说明常见的索引类型

  • 按 数据结构 分类:B+树索引,Hash索引,Full-text索引
  • 按 物理存储 分类:聚簇索引(主键索引),二级索引(辅助索引)
  • 按 字段特性 分类:主键索引,唯一索引,普通索引,前缀索引
  • 按 字段个数 分类:单列索引,联合索引

4. 请列举索引失效的几种常见场景

  • 对索引使用左或者右模糊匹配,如 like '%xx',like '%xx%'
  • 对索引使用函数
  • 对索引进行表达式计算
  • 对索引隐式类型转换
  • 联合索引非最左匹配
  • where子句中的 or
  • 数据量太小,MySQL觉得全表扫描更快

    5. 在什么情况下应该使用索引来优化查询?

  • 字段具有唯一性限制
  • 经常用于 where查询条件的字段,如果不是一个字段,可以建立联合索引
  • 经常用于 group by 和 order by的字段,这样查询的时候就不需要再次排序了,建立索引后,在B+Tree中的记录都是排序好的。

    6. 什么是数据库事务?它的基本特性是什么?

  • 事务是代表单个工作单元的一组SQL语句,当我们需要对数据库进行多次更改的情况下,要使用事务,我们希望所有这些更改作为一个单元一起成功或失败
  • 事务的四大特性 (ACID)

    • 原子性(Atomicity) :事务中的所有操作要么全部完成,要么全部不完成;
    • 一致性(Consistency) :事务完成后,数据库必须从一个一致状态转化到另一个一致状态,数据库始保持一致的状态;
    • 隔离性(Islation) :一个事务的执行不应影响其他事务的执行;
    • 持久性(Durability) :一旦事务提交,其结果应该永久保存在数据库中,即使系统发生故障;

      7. 事务的隔离级别是什么?它如何影响并发事务的执行?

      标准的SQL定义了4个事务隔离级别,隔离级别逐渐增高,性能和可扩展性逐渐降低,因为限制了并发。在MySQL中,默认的事务隔离级别是‘可重复读’。

  • 读未提交 :允许读取未提交的数据,最低的隔离级别
  • 读已提交 :给予了我们的事务一定的隔离,使得该事务只能读取已提交的数据,避免了脏读。
  • 可重复读 :我们读取的数据是可重复和一致的,就算有其他事务更改了数据,我们会看到首次读取就创建的快照。
  • 序列化 :它能保证当有别的事务在更新数据时,我们的事务能够知晓变动,如果有其他事务修改了可能影响查询结果的数据,我们的事务必须等它们完成,这样事务就会按序列化执行。

    8. 在数据库中,常见的并发问题有哪些?如何通过事务管理避免这些问题?

  • 丢失更新
  • 当两个事务尝试更新相同的数据并且没有上锁时,就会发生这种情况,比如两个事务更新同一条记录的不同列的信息,较晚提交的事务会覆盖较早事务做的更改,使得较早事务做的更改缺失。
  • 使用锁,防止两个事务同时更新同样的数据,MySQL提供的默认锁的锁粒度是行级锁。
  • 脏读
  • 一个事务读取了尚未被提交的数据,如果该数据被退回的话,该事务就是读取了一个不存在的数据,就是脏读。
  • 为了解决这个问题,我们需要为事务建立隔离级别,“读已提交”,这样事务修改的数据不会立马被其他事务读取,除非它提交了。
  • 不可重复读(不一致读)
  • 当我们在事务中添加更多隔离时,我们可以保证事务只能读取已提交的数据,但如果在事务过程中,读取了某个数据两次,并得到了不同的结果就是不可重复读问题。
  • 我们就需要增加事务隔离级别,我们要将它与其他事务隔离,“可重复读”,确保数据更改对该事务不可见,只看事务开始前那一刻的数据信息。
  • 幻读
  • 对于突然出现或者缺失的数据,我们无法在查询中看到它们,因为它们是在执行查询后才添加、更新、删除的。
  • 为此,我们有另一个隔离级别为”序列化“,它能保证当有别的事务在更新数据时,我们的事务能够知晓变动,如果有其他事务修改了可能影响查询结果的数据,我们的事务必须等它们完成,这样事务就会按序列化执行。

    9. 什么是 MVCC(多版本并发控制)?

    MVCC(多版本并发控制) 是一种用于数据库管理系统的并发控制机制,它的目的是提高数据并发访问的效率,减少锁竞争,降低对锁的依赖。MVCC具体实现是通过 Read View版本链机制

  • Read View 是实现 MVCC 机制的一个关键概念,包含四个重要字段:

    • m_ids:当前数据库中活跃事务的事务 ID 列表,活跃事务是指已启动但尚未提交的事务。

      • min_trx_id:指的是 m_ids 中的最小事务 ID。
    • max_trx_id:数据库中最大的事务 ID 加 1。也就是说,它表示当前数据库中还未提交的最大事务 ID。
    • creator_trx_id:创建该 Read View 的事务 ID。
  • 在 InnoDB 存储引擎中,每条记录的行格式包含两个隐藏字段:

    • trx_id:每当一个事务对某条记录进行更改时,系统会将该事务的事务 ID 记录在 trx_id 中。
    • roll_pointer:每次修改记录时,旧版本的记录会被写入 undo 日志,这个字段指向旧版本记录的地址,通过这个指针可以追溯到修改前的记录,这就是所谓的版本链。

      具体实现过程:
  • 通过 Read View 和版本链机制,InnoDB 实现了事务的并发控制。在事务开始时,系统会创建一个 Read View,并根据该事务的可见性来读取数据:

    • 可见的事务 ID 是小于 min_trx_id 的事务 ID,这些事务的数据对当前事务是可见的。
    • 不可见的事务 ID 是大于等于 max_trx_id 的事务 ID,当前事务无法读取这些事务的数据。
  • 当查询数据时,系统会检查每条记录的 trx_id 来判断其是否符合事务的可见性要求。如果该记录的 trx_id 不符合,则系统会通过 roll_pointer 找到该记录的旧版本,从而实现数据的读取。

    • 通过这种机制,InnoDB 能够在高并发环境下保持事务的隔离性,同时确保每个事务能读取到基于其创建时的 Read View 可见的数据。这种多版本并发控制(MVCC)技术有效地解决了读写冲突的问题,并允许事务以一致的方式读取数据。

    10. 为什么 MySQL 默认的可重复读隔离级别能够在很大程度上避免幻读?在高并发环境下,这两种解决方案的效果如何?

  • MySQL虽然支持4种隔离级别,但是与SQL标准种规定的各级隔离级别允许发生的现象却有些出入。MySQL InnoDB引擎的默认隔离级别虽然是可重复读,但是它很大程度上避免了幻读现象,解决的方案有两种:

    • 针对快照读,普通的select语句,是通过MVCC的方式解决了幻读。
    • 针对当前读,select…for update等,是通过加临界锁(记录锁+间隙锁)。当执行当前读时,会在范围加上临界锁,其他事务如果在锁的范围内插入或删除一条记录,就会被阻塞,很好地避免了幻读问题。

      11. 数据库中的三种日志类型分别是什么?它们各自的作用是什么?

  • undo log(回滚日志) :是InnoDB存储引擎层生成的日志,实现了事务中的原子性,主要用于事务回滚和MVCC
  • redo log(重做日志) :是InnoDB存储引擎层生成的日志,实现了事务中的持久性,主要用于掉电等故障恢复。
  • binlog(归档日志) :是Server层生成的日志,主要用于数据备份和主从复制。

就业陪跑训练营学员投稿

欢迎关注 ❤

我们搞了一个免费的面试真题共享群,互通有无,一起刷题进步。

没准能让你能刷到自己意向公司的最新面试题呢。

感兴趣的朋友们可以加我微信:wangzhongyang1993,备注:思否面试群。


王中阳讲编程
805 声望297 粉丝