<audio id="audio" title="特别放送（二）| 经典面试题讲解第二弹" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/7f/bc/7f9585f59083444c3c3c044c7210ebbc.mp3"></audio>

你好，我是朱晓峰。

到这里，“进阶篇”的内容咱们就学完了。今天，我给你准备了7道面试题。这些面试题涵盖了这个模块的核心内容，我们一起借助面试题来复习一下。我不仅会给你提供正确答案，还会带你深入分析这些问题，让你真正能够做到举一反三。

好了，话不多说，我们现在开始。

## 第一题

**日志文件对数据库的故障恢复至关重要。下面这些关于日志文件的描述，正确的是：**

1. MySQL日志记录的顺序可以与并发操作的执行顺序不一致
1. 为了确保数据库是可恢复的，必须确保先写数据库后写日志
1. 日志文件中检查点的主要作用是提高系统出现故障后恢复的效率
1. 系统故障恢复必须使用日志文件以保证数据库系统重启时能正常恢复，事务故障恢复不一定需要使用日志文件

答案：选项3。

解析：

选项1是错误的。MySQL日志记录的顺序是严格按照操作执行的顺序记录的，不会出现日志记录的顺序与并发操作执行的顺序不一致的情况。

选项2也是错误的。MySQL的日志系统遵循WAL（Write-Ahead Logging）机制，也就是所谓的先写日志，后写数据库的机制。由于记录日志是顺序写入磁盘，而写入数据库的磁盘操作需要对磁头定位，因而写入日志的速度要远比写入数据快。为了提高执行的效率，MySQL执行的是先写日志，日志写入成功之后，就回复客户端操作成功，对数据库的磁盘写入则在之后的某个阶段执行。这样，即便遇到系统故障，由于有了日志记录，就可以通过日志对数据库进行恢复了。WAL机制包括3个规则：

- 对数据的修改操作必须在写入数据库之前写入到日志文件中；
- 日志必须严格按序记录，就是说，如果A操作发生在B操作之前，那么在日志中，A操作的记录必须在B操作的记录之前；
- 事务提交之后，必须在日志写入成功之后，才能回复事务处理成功。

选项3是正确的，检查点的作用是加快数据恢复的效率。当修改数据时，为了提高存取效率，采用的策略是先记录日志，实际的数据修改则发生在内存中，这些数据修改是没有写入数据库的，叫做脏页。MySQL把这些脏页分成小的批次，逐步写入磁盘中。因为如果把所有的脏页都一次性写入磁盘，会导致磁盘写入时间过长，影响到用户SQL操作的执行。检查点的作用就是标记哪些脏页已经写入磁盘。这样，当遇到故障时，MySQL可以从检查点的位置开始，执行日志记录的SQL操作，而不是把整个日志都检查一遍，所以，大大提高了故障恢复的效率。

选项4也是错误的。系统故障恢复必须使用日志文件以保证数据库系统重启时能正常恢复，这个表述是正确的，但后面的表述“事务故障恢复不一定需要使用日志文件”则是错误的。事务故障的恢复也必须要用到日志文件，事务故障恢复需要用到的日志文件有3个，分别是回滚日志、重做日志和二进制日志。

- 回滚日志：如果事务发生故障，可以借助回滚日志，恢复到故障前的状态，所以回滚日志对事务故障恢复有用。
- 重做日志：事务中的操作对数据更新进行提交时，会记录到重做日志，对数据的更新则只会发生在内存中，实际的数据更新写入磁盘，则会由后台的其他进程异步执行。如果这个时候事务故障，内存中的数据丢失，就必须要借助重做日志来找回。所以，重做日志对事务故障恢复有用。
- 二进制日志：在主从服务器架构的模式下，从服务器完全依赖二进制日志同步主服务器的操作，如果事务发生故障，从服务器只能依靠主服务器的二进制日志恢复。

## 第二题

**MySQL支持事务处理吗？**

参考答案：

这个问题跟数据表用的是什么存储引擎有关。如果用的是Innodb，则支持事务处理；如果用的是MyISAM，则不支持事务处理。

MySQL  8.0  默认的存储引擎是Innodb，Innodb是支持事务处理的。在默认的情况下，MySQL启用AUTOCOMMIT模式，也就是每一个SQL操作都是一个事务操作，如果操作执行没有返回错误，MySQL会提交事务；如果操作返回错误，MySQL会执行事务回滚。

你也可以通过执行“START TRANSACTION”或者“BEGIN”来开始一个事务，这种情况下，就可以在事务处理中包含多个SQL操作语句，一直到“COMMIT”语句提交事务，或者是“ROLLBACK”语句回滚事务，来结束一个事务操作。

MyISAM存储引擎是不支持事务操作的，如果你对一个存储引擎是MyISAM的数据表执行事务操作，不管你是否执行“COMMIT”或者是“ROLLBACK”，都不会影响操作的结果。你可以通过下面的SQL语句来查看表的存储引擎：

```
mysql&gt; SHOW CREATE TABLE demo.test;
+-------+------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+------------------------------------------------------------------------------------------------------------------+
| test | CREATE TABLE `test` (
`aa` int DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-------+------------------------------------------------------------------------------------------------------------------+
1 row in set (0.02 sec)

```

## 第三题

**下面这些关于MySQL视图的描述中，错误的是：**

1. 视图是MySQL提供给用户以多种角度观察数据库中数据的重要机制
1. 视图可以对重构数据库提供一定程度的逻辑独立性
1. 所有视图都是可查询和可更新的
1. 对视图的一切操作都会转换成对数据表的操作

答案：选项3。

解析：

选项1的描述是正确的。视图其实就是存储在服务器中的查询语句，可以通过编写不同的查询语句，从数据库中抽取需要的数据。也就相当于从多种角度观察数据库中的数据。

选项2的描述是正确的。视图通过查询语句从数据库中抽取需要的数据，如果遇到数据表结构的变更，可以通过修改查询语句，使视图返回的结果集中的字段保持不变。因此，视图可以一定程度不受实际数据表结构的变化的影响，具备一定的逻辑独立性。

选项3的描述是错误的，所有的视图都可以查询，但不是所有的视图都可以更新。比如，定义视图的查询语句如果包含分组，由于无法对实际数据表中的记录定位，所以这样的视图是不支持数据更新操作的。

选项4的描述也是正确的。视图不过是一段查询语句，视图并不保存实际数据，对视图的任何操作，最终都会转换到实际数据表。

## 第四题

**下面关于存储过程的描述中，不正确的是：**

1. 存储过程实际上是一组SQL语句
1. 存储过程预先被编译存放在数据库服务器上
1. 存储过程与数据库无关
1. 存储过程可以完成某一特定的业务逻辑

答案：选项3。

解析：

选项1的描述正确，存储过程的程序体就是一组SQL语句，调用存储过程，实际上就是执行了一组SQL操作。

选项2的描述正确，存储过程创建完成之后，就是经过了编译的过程，以服务可以执行的形式存放在服务器中。

选项3的描述是错误的，存储过程是数据库的一部分，不能独立于数据库而存在。

选项4的描述是正确的，创建存储过程的目的，就是为了高效地完成某一特定的业务逻辑。

## 第五题

在MySQL中，有学生表（学号，姓名，年龄，所在系），其中学号是主键。在这个表上建有视图V1，V1的定义语句是：

```
CREATE VIEW V1 AS SELECT 姓名，年龄，所在系
FROM 学生表 WHERE 年龄&gt;=(SELECT AVG(年龄) FROM 学生表);

```

有下列操作语句：

```
A.UPDATE V1 SET 年龄=年龄-1;
B.SELECT * FROM V1 WHERE 年龄&gt;20;
C.DELETE FROM V1 WHERE 年龄&gt;20;
D.INSERT INTO V1 VALUES (‘张三’,20,’计算机系’);

```

以上语句能够正确执行的是：

1. A、B和D
1. 仅B
1. 仅B和C
1. 仅A、B和C

答案：选项2。

解析：这道题考核的要点是，如果定义视图的SQL语句中包含了聚合函数，就不能对视图中的数据进行DML操作。

## 第六题

**什么是游标？如何知道游标已经走到了最后？**

参考答案：

由SELECT语句返回的完整行集（包括满足WHERE语句中条件的所有行）称为结果集。MySQL中的SQL操作，会对整个结果集起作用。应用程序，特别是交互式的联机应用程序，并不总能将整个结果集作为一个单元来进行有效的处理，这些应用程序需要一种机制，以便每次处理一行或者一部分行。游标就是提供这种机制的，是对结果集的一种扩展。

具体而言，MySQL的游标有以下特点：

- 可以逐条查看数据集中的记录；
- 一次只能查看一条记录；
- 只能向一个方向扫描数据，并且不能跳跃；
- 游标是只读的。

可以使用条件处理语句“DECLARE  CONTINUE  HANDLER  FOR  NOT  FOUND”，来判断游标到达了结果集的最后。

## 第七题

下面关于触发器的叙述中，错误的是：

1. 触发器是一种特殊的存储程序
1. 触发器必须创建在一个特殊的表中
1. 触发器通过CALL调用
1. 触发器有助于实现数据库的完整性、安全性和主动性

答案：选项3。

解析：

触发器也是存储在服务器端，是一种存储程序，触发器监控的对象是一个特定的表，触发器可以记录日志、进行安全性检查，并且无需应用程序的控制，可以由数据操作的事件驱动，所以选项1、2、4都是正确的。

触发器不能由CALL调用，而是由事件驱动，所以3是错误的。

## 总结

今天，我们借助几个面试题，回顾了日志、游标、视图、存储过程和触发器的相关内容。如果你发现回答这些试题有困难，一定要及时回去复习一下。

刷题不是目的，真正的目的是对你掌握知识的熟练程度进行检验，发现问题，查漏补缺。只有深入了解相关的知识背景、工具的运行机制和原理，才能牢固掌握，在实践中灵活运用。
