准备面试可能聊到的mysql面试聊天内容,看到文章的小伙伴、相见即是缘分。
希望大家可以在评论区补充更多的面试内容,内容有错误或不同的观点也希望可以指出。
架构: 一主多从、读写分离
主从复制的模式
- 异步复制(默认) - 主库不管从库有没有接收并执行binlog
- 半同步模式 - 主库写binlog 后、会等待最少一个从库返回确认标识(从库接收到就返回)
- 全同步模式 - 事物提交前必须大部分节点收到确认并执行才认为提交成功(通过分布式一致性协议[Paxos/raft])
异步同步的过程
- 客户端向主库发送一条修改的sql
- 主库执行成功并将操作写入binlog
- 从库的IO线程连接主库、获取binlog日志内容
- 从库将 binlog 内容写入 relay log
- 从库的sql线程读取 relay log 执行sql
从库拉取binlog的方式从用的是持续监听的方式, 向主库发送 com_binlog_dump 命令建立长连接并保持阻塞状态
- 一旦主库有binlog产生、就会立刻推送给从库
- 从库的io线程收到binlog后会写入本地 realylog
会不会主从数据不一致、什么情况下会丢失数据、宕机恢复策略。
mysql 请求流程
8.0版本后移除了查询缓存
mysql的事务、日志
两阶段提交 - redolog与binlog要么都写、或都不写
- 阶段一 : prepare(准备阶段)
- 执行 sql 语句,并生成 undolog(写入 undo log segment -> undo tablespace(磁盘))、 redolog (处于内存)
- innodb 把 redolog 写入磁盘,并标记为 prepare(预提交)状态
- 通知 mysql server 层可以写入 binlog。 redolog 已持久化
- 阶段二:commit(提交阶段)
- server层 写入 binlog
- redolog 由 prepare 更新为 commit
- 事物完成
执行过程中 mysql 宕机异常怎么办、
- 处于 准备阶段、写完了 redolog 但未写 binlog回滚
- 处于 提交阶段、binlog 已存在、 redolog状态未更新、则根据binlog补全redolog为commit。
mysql 有多少种日志
- binlog:server层,用于主从同步及数据恢复
- redolog:重做日志,innodb层,保证事物持久性、D,崩溃恢复时重做已提交但未持久化到磁盘的事务
- undolog:回滚日志,innodb层,用于事物回滚撤销未提交的更改、MVCC版本控制、在可重复读与读提交的隔离级别下、通过 undolog构建历史版本数据。
- relaylog:用于从库执行binlog
- error log : 启动、停止、崩溃、异常等系统日志
- show log: 慢日志
- 一致性:执行前后读取结果是一致的、ACID 整体配合 + 约束机制
- 持久性:redo log + 两阶段提交 + doublewrite
- 隔离性:隔离级别 + MVCC + 锁
- 原子性:要么全部成功、要么全部失败 undo log + 回滚机制
隔离级别:
- 读未提交
- 读提交 - 脏读:会读取到另一个事物未提交的数据
- 可重复读 - 不可重复读: 两次读取、读取到了不一样的内容
- 串行化 - 幻读: 批量查询结果数量时行数不一致
mysql 优化
读优化
- 增大连接数、调整缓冲区大小
- sql查询优化:构建索引
- 增大缓冲区大小 innodb_buffer_poll_size、保证更多的数据与内存留在内存中
- 应用层缓存、缓存中间件redis
- 启用慢日志、explain 分析、监控性能指标
mysql的索引有多少种、什么情况下会失效
- 主键索引 - 主键默认为聚簇索引、普通索引叶子节点存储的id、聚簇索引存储的row
- 唯一索引
- 联合索引 - 最左匹配原则
- 前缀索引
- 普通索引
- 哈希索引
- 全文索引
- 覆盖索引 - 查询的列存在索引中,可以减少一次回表
索引失效
- 函数运算、含括:字段类型不匹配 - 使用了隐式类型转换
- like - 左边使用了通配符
- 使用了or
- 使用 != 查询
写优化
- 避免大事物防止锁表时间过长
- 批量写入多值插入、
- 分库分表
- innodb 刷盘策略调整、合理设置日志缓冲区
- 分库分表、读写分离、异步写入、批量操作
- 加强硬件、ssd优化
数据一致性问题
一致性分为弱一致性(最终一致性)与强一致性
方案
- 强一致性:写后同步缓存
- 先写后删 存在问题脏数据回填
- 延迟双删、第二次删除缓存
- 异步mq更新缓存