这些都是面试常见的问题,看看下面的问题你都能答得上来吗?
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. 列举并简要说明常见的索引类型
- type:指查询到所需行的方式,从好到坏的顺序:
- 按 数据结构 分类: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,备注:思否面试群。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。