当前位置: 主页 > 天剑狂刀BT页游 >

数据库精选 60 道面试题(2)

时间:2022-03-13 18:56来源:8N.org.Cn 作者:天剑狂刀私服 点击:

- 反过来,假设一个业务的更新模式是写入之后马上会做查询,那么即使满足了条件,将更新先记录在 change buffer,但之后由于马上要访问这个数据页,会立即触发 merge 过程。这样随机访问 IO 的次数不会减少,反而增加了 change buffer 的维护代价。

12、MySQL 是如何判断一行扫描数的?

MySQL 在真正开始执行语句之前,并不能精确地知道满足这个条件的记录有多少条。

而只能根据统计信息来估算记录数。这个统计信息就是索引的“区分度。

13、MySQL 的 redo log 和 binlog 区别?

数据库精选 60 道面试题

14、为什么需要 redo log?

redo log 主要用于 MySQL 异常重启后的一种数据恢复手段,确保了数据的一致性。

其实是为了配合 MySQL 的 WAL 机制。因为 MySQL 进行更新操作,为了能够快速响应,所以采用了异步写回磁盘的技术,写入内存后就返回。但是这样,会存在 crash后内存数据丢失的隐患,而 redo log 具备 crash safe 的能力。

15、为什么 redo log 具有 crash-safe 的能力,是 binlog 无法替代的?

第一点:redo log 可确保 innoDB 判断哪些数据已经刷盘,哪些数据还没有

redo log 和 binlog 有一个很大的区别就是,一个是循环写,一个是追加写。也就是说 redo log 只会记录未刷盘的日志,已经刷入磁盘的数据都会从 redo log 这个有限大小的日志文件里删除。binlog 是追加日志,保存的是全量的日志。

当数据库 crash 后,想要恢复 未刷盘但已经写入 redo log 和 binlog 的数据到内存时,binlog 是无法恢复的。虽然 binlog 拥有全量的日志,但没有一个标志让 innoDB 判断哪些数据已经刷盘,哪些数据还没有。

但 redo log 不一样,只要刷入磁盘的数据,都会从 redo log 中抹掉,因为是循环写!数据库重启后,直接把 redo log 中的数据都恢复至内存就可以了。

第二点:如果 redo log 写入失败,说明此次操作失败,事务也不可能提交

redo log 每次更新操作完成后,就一定会写入日志,如果 写入失败,说明此次操作失败,事务也不可能提交。

redo log 内部结构是基于页的,记录了这个页的字段值变化,只要crash后读取redo log进行重放,就可以恢复数据。

这就是为什么 redo log 具有 crash-safe 的能力,而 binlog 不具备。

16、当数据库 crash 后,如何恢复未刷盘的数据到内存中?

根据 redo log 和 binlog 的两阶段提交,未持久化的数据分为几种情况:

change buffer 写入,redo log 虽然做了 fsync 但未 commit,binlog 未 fsync 到磁盘,这部分数据丢失。

change buffer 写入,redo log fsync 未 commit,binlog 已经 fsync 到磁盘,先从 binlog 恢复 redo log,再从 redo log 恢复 change buffer。

change buffer 写入,redo log 和 binlog 都已经 fsync,直接从 redo log 里恢复。

17、redo log 写入方式?

redo log包括两部分内容,分别是内存中的 日志缓冲(redo log buffer)和磁盘上的 日志文件(redo log file)。

MySQL 每执行一条 DML 语句,会先把记录写入 redo log buffer(用户空间),再保存到内核空间的缓冲区 OS-buffer 中,后续某个时间点再一次性将多个操作记录写到 redo log file(刷盘)。这种先写日志,再写磁盘的技术,就是 WAL

数据库精选 60 道面试题

可以发现,redo log buffer写入到redo log file,是经过OS buffer中转的。其实可以通过参数innodb_flush_log_at_trx_commit进行配置,参数值含义如下:

0:称为 延迟写,事务提交时不会将redo log buffer中日志写入到OS buffer,而是每秒写入OS buffer并调用写入到redo log file中。

1:称为 实时写,实时刷”,事务每次提交都会将redo log buffer中的日志写入OS buffer并保存到redo log file中。

2:称为 实时写,延迟刷。每次事务提交写入到OS buffer,然后是每秒将日志写入到redo log file。

18、redo log 的执行流程?

我们来看下Redo log的执行流程,假设执行的 SQL 如下:

update T seta =1 whereid =666

数据库精选 60 道面试题

MySQL 客户端将请求语句 update T set a =1 where id =666,发往 MySQL Server 层。

MySQL Server 层接收到 SQL 请求后,对其进行分析、优化、执行等处理工作,将生成的 SQL 执行计划发到 InnoDB 存储引擎层执行。

InnoDB 存储引擎层将 a修改为1的这个操作记录到内存中。

记录到内存以后会修改 redo log 的记录,会在添加一行记录,其内容是 需要在哪个数据页上做什么修改

此后,将事务的状态设置为 prepare ,说明已经准备好提交事务了。

等到 MySQL Server 层处理完事务以后,会将事务的状态设置为 commit,也就是提交该事务。

------分隔线----------------------------