Appearance
第3章 数据库:MySQL / Redis / Vastbase
对应简历:技能第8条「熟练掌握 MySQL 主备复制、备份恢复(mysqldump / XtraBackup)与慢查询优化」;技能第9条「熟悉 Redis 主备 / 哨兵架构,熟悉 Vastbase(OpenGauss,PostgreSQL 系)、RocketMQ、Nacos 的部署与维护」;项目一「负责 Vastbase G100 数据库一主一备高可用集群的部署、license 配置与环境验收」;项目二「配套规划云数据库 MySQL(主备高可用)、Redis(双机热备)、RocketMQ、Nacos 及数据库审计等云服务」。 口径提醒:MySQL/Redis 按"课程实验 + 云服务运维"结合讲(项目二是云托管主备,自建主从按课程实验口径);Vastbase 是真实生产部署经历,放开讲。
3.1 MySQL 安装方式与初始化流程 【理解】
标准回答:MySQL 安装三种方式按定制度排序:yum 或 rpm 安装最快但路径和参数不能定制,CentOS 上还要先卸载 mariadb-libs 否则依赖冲突装不上;二进制 tar 包解压即用、目录自定、升级回滚方便,是我最喜欢用的方式;源码编译完全定制但耗时最长,只有特殊需求才用。
初始化流程:5.7 和 8.0 用 mysqld --initialize 生成 data 目录和一个随机临时密码(写在错误日志里,要 grep "temporary password" 找出来),或者 --initialize-insecure 生成空密码实例——这和 5.6 的 mysql_install_db 脚本是两套机制,面试常考版本差异。然后 systemctl 启动、用临时密码登录后 alter user 改密、按需跑安全初始化(删匿名账号、删 test 库、禁远程 root)。
配置文件 /etc/my.cnf 的核心项我心里有一张清单:datadir 数据目录、socket、character_set_server=utf8mb4、server_id(主从必须不同)、log_bin 开 binlog——最后两项就是主从和按时间点恢复的地基。
追问链:
- 追问1:忘记 root 密码怎么办? → 答:标准流程四步:my.cnf 的 mysqld 段加
skip-grant-tables跳过授权表 → 重启 mysqld → 免密登录后用 update 或 alter user 改掉密码 → 去掉参数再正常重启。原理是让 mysqld 启动时不加载存权限的授权表,任何账号都能进。操作时要注意两点:这个状态下任何人都能连,必须在本机或维护窗口做;改完立刻恢复配置,别让裸奔状态过夜。 - 追问2:MySQL 启动不了怎么排查? → 答:我的三步链:第一步看错误日志,log_error 指向的文件里会直接写原因——权限不对、端口占用、参数拼写错误,八成的问题它都会告诉你;第二步
mysqld --defaults-file=/etc/my.cnf前台手工启动,让报错直接打到屏幕上;第三步查 datadir 的属主属组必须是 mysql:mysql,还有磁盘满不满。最重要的一条红线:绝不能一怒之下重新 initialize——那等于删库,data 目录里是全部数据。我在课程实验里把每种启动失败都人为制造过一遍,所以排障时心里有谱。 - 追问3:8.0 相比 5.7 建用户有什么变化? → 答:最大的变化是授权模型拆开了:8.0 必须先
create user再grant,两条命令分工明确;5.7 允许grant ... identified by '密码'一条龙(8.0 已废弃这种写法)。另外 8.0 默认认证插件换成 caching_sha2_password,安全性更好但老版本客户端和驱动连不上,兼容办法是建用户时显式identified with mysql_native_password。这个差异我真实遇到过:新库老应用连不上报认证错误,一条命令解决。
关联话术:"项目二我用的是移动云 MySQL 8.0 主备实例——我的职责是规格规划(8 核 16G、300G SSD)、安全组放行、账号权限和连接信息交付给应用;自建安装维护我在课程实验里完整做过,初始化脚本和 2.12 的备份脚本同源。这样答既不虚报生产经历,又展示了云上真实职责。"
3.2 MySQL 体系结构一句话与 SQL 执行过程 【理解】
标准回答:体系结构我用一句话概括:客户端连接器 → 服务层(连接管理、分析器、优化器)→ 存储引擎层(InnoDB 插件式)→ 文件系统。一条 select 语句的旅程是:连接器做认证并取出该账号的权限快照 → 8.0 已经删除查询缓存(8.0 以前有但命中率低被废弃)直接进分析器 → 分析器做词法语法检查,把字符串解析成结构化语句 → 优化器基于代价估算选索引、决定 join 顺序,生成执行计划 → 执行器按计划调用存储引擎接口逐行取数据返回客户端。
所谓"实例"就是 mysqld 进程本身:一组后台线程(master thread、IO 线程、purge 等)加内存结构(Buffer Pool、各种 cache)加磁盘文件。理解这条链路的价值在于:后面所有话题——慢查询在优化器层、binlog 在服务层、redo 在引擎层——都能挂到这张地图上,答体系结构其实是在给面试官展示你的知识有结构。
追问链:
- 追问1:InnoDB 和 MyISAM 区别? → 答:核心差异六条:InnoDB 支持事务和崩溃自动恢复,MyISAM 不支持;InnoDB 是行级锁,MyISAM 只有表级锁;InnoDB 是聚簇索引(数据和主键索引一体),MyISAM 索引和数据分离;InnoDB 支持 MVCC 和外键,MyISAM 都没有;InnoDB 支持在线热备,MyISAM 备份要锁表。结论一句话:5.5 之后默认引擎就是 InnoDB,现在的生产环境只谈 InnoDB,MyISAM 只读表极特殊场景才考虑。答的时候点到"为什么默认换成 InnoDB"——事务和行锁是 OLTP 的命根子。
- 追问2:Buffer Pool 的作用? → 答:Buffer Pool 是 InnoDB 在内存里的数据页和索引页缓存,默认页大小 16K。读:先看池里有没有目标页,有就是命中免磁盘 IO;写:先改池里的页(变成脏页)再异步刷盘——所以读写性能都高度依赖命中率。它带来的第一个调优结论就是
innodb_buffer_pool_size是 MySQL 最重要的参数,一般给到物理内存的 50% 到 70%,专用数据库机器还可以更高。我讲这个参数时习惯带一句"为什么是这个比例":留内存给 OS 缓存、连接内存和临时表。
关联话术:"体系结构这题我是当地基答的:一句话讲完结构,再顺着'一条 SQL 的旅程'走一遍,30 秒内把服务层和引擎层的分界讲清。这个分界正好接后面三大日志(3.3)——binlog 在服务层、redo 和 undo 在引擎层——把两道题串成一张图,面试官会觉得我知识成体系而不是零散背诵。"
3.3 binlog / redo / undo 三大日志区别 【必背】
标准回答:三大日志我用"一句话分工"开场:binlog 是服务层的归档日志,服务复制和时间点恢复;redo 是 InnoDB 引擎层的前滚日志,保证持久性;undo 是引擎层的回滚日志,保证原子性。展开说:binlog 记录所有 DDL 和 DML 的逻辑日志,三种格式——row 按行记录变更最安全(8.0 默认)、statement 记 SQL 语句量小但 now() 这类函数主从不一致、mixed 自动切换;show master status 看当前文件和位点,mysqlbinlog 工具可以解析内容。
redo log 是物理日志,记录"某个页做了什么修改",核心机制是 WAL——先写日志再刷数据页,事务提交时 redo 落盘了就算持久化成功,宕机后靠 redo 前滚把没来得及刷盘的修改补回来,这就是崩溃恢复。
undo log 记录修改前的反向操作,事务回滚靠它执行逆操作,MVCC 的多版本读也靠 undo 链找历史版本。最后必须主动提"双一标准":sync_binlog=1 加 innodb_flush_log_at_trx_commit=1,每个事务都强制落盘,最安全也最耗 IO,按业务在安全和性能之间取舍。
追问链:
- 追问1:有了 binlog 为什么还要 redo? → 答:两个层面回答。功能层:binlog 是服务层的逻辑日志,没有自动崩溃恢复能力,谁来把"binlog 写了但数据页没刷"的状态补齐?redo 就是干这个的——物理到页、支持从 checkpoint 断点续刷。历史层:binlog 是 MySQL 服务层的东西,所有引擎共享;redo 是 InnoDB 自己的,InnoDB 在成为默认引擎之前就存在了。所以一个管"复制与归档"、一个管"引擎级持久性",谁也替代不了谁——这个问题答到"层次不同、职责不同"就到位了。
- 追问2:一条 update 的完整落盘链路? → 答:按顺序走:数据页如果不在内存,先从磁盘读进 Buffer Pool → 写 undo log 记录旧值(支撑回滚和 MVCC)→ 在内存中修改数据页(该页变脏页)→ 写 redo log buffer 并在事务提交时刷到 redo 文件 → 写 binlog → redo 与 binlog 之间做内部两阶段提交保证一致 → 返回客户端成功 → 脏页由 master thread 按 checkpoint 机制异步刷盘。这套顺序背下来,"WAL、先记日志后改数据、两阶段提交"这些概念就都有了着落。
- 追问3:binlog 三种格式你们用哪种? → 答:用 row,8.0 默认也是 row。理由:row 按行记录变更的前后镜像,主从复制一致性最强,delete 和 update 影响的行一模一样重放,不存在 statement 那种函数、随机值导致主从不一致的风险。代价是日志量大——一条 update 一万行就是一万条记录,靠 binlog 压缩和合理的 expire 设置控制空间。这个取舍我在云控制台配置 binlog 保留期时确认过参数含义。
- 追问4(深挖):什么是 2PC? → 答:指 binlog 和 redo 之间的事务内部两阶段提交:第一阶段 redo 写入并标记为 prepare 状态;第二阶段 binlog 成功写入后,事务标记为 commit。这样设计的目标是任何时刻宕机,恢复时都能根据"redo 处于 prepare 且 binlog 完整与否"决定提交还是回滚,保证两个日志的逻辑一致,避免"binlog 有而 redo 无"或反之的主从分叉。细节我理解到这个层面,生产上没有手工干预过中间状态——如实说到这里。
关联话术:"这套日志体系是我讲'数据为什么不丢、误删怎么救'的地基。两个项目我都能挂上:银行 Vastbase 是 PG 系的物理复制,我用 binlog 的概念对比着讲 WAL 日志流复制;移动云云 MySQL 的 binlog 保留 7 天是我配置的——同一套理论、两种落地,这样答能体现理解而不是背题。"
实操模板:
sql
show variables like 'log_bin%'; -- binlog开关与格式
show master status; -- 当前binlog文件与位点
show binlog events in 'binlog.000003'; -- 看事件
show variables like '%flush_log_at_trx_commit%';
-- my.cnf: log_bin=/data/mysql/binlog server_id=1 binlog_format=row
-- sync_binlog=1 innodb_flush_log_at_trx_commit=1 binlog_expire_logs_seconds=6048003.4 主从复制原理与搭建步骤 【必背】
标准回答:主从复制我用"三线程模型"讲:主库上的 dump 线程负责推送 binlog,从库上的 IO 线程负责接收写进中继日志,从库上的 SQL 线程负责重放中继日志。完整流程:从库执行 change master to 配好主库地址和复制账号 → start slave 后 IO 线程连上主库,主库为它创建 dump 线程 → dump 线程按从库报告的 binlog 位点开始投递事件 → 从库 IO 线程收到后先记录接收位点,把事件写入 relay log → SQL 线程从 relay log 里上次回放到的位置继续读取重放 → 回放完的 relay log 由 relay_log_purge 定期清理。
GTID 模式给每个事务一个全局唯一编号,从库 change master 用 master_auto_position=1 自动对齐,不用手工记"文件名+位点",搭从库和故障切换都简单得多。
还要主动讲一致性等级:默认异步复制,主库提交不等待从库,主库宕机可能丢最新事务;半同步复制要求至少一个从库 ACK 收到 binlog 才向客户端返回成功,大幅降低丢失窗口。
追问链:
- 追问1:给运行 2 年的库搭从库,要停主库吗? → 答:不需要停。标准做法:夜里低峰在主库做全备,mysqldump 加
--single-transaction(InnoDB 一致性快照不锁表)和--source-data=2(把 binlog 位点以注释写进备份文件)→ 把全备导入新从库 → 在从库 change master to 时使用备份文件里记录的位点(GTID 模式更简单,直接 auto position)→ start slave 追增量。全程主库正常提供服务,业务只感知到备份期间的备份 IO。 - 追问2:怎么确认主从正常? → 答:
show slave status\G看三件套:Slave_IO_Running 和 Slave_SQL_Running 必须双 Yes,Seconds_Behind_Master 理想是 0 表示没有延迟。任何一个 No 就往下看 Last_IO_Error 或 Last_SQL_Error 的具体报错——报错信息基本都会直指原因(连接失败、权限、重复建对象)。巡检脚本里就抓这三个字段,异常即告警,这也是我讲"监控要覆盖复制链路"的例证。 - 追问3:IO 线程 No 常见原因? → 答:分两类。连接类:网络不通、主库 IP 端口账号密码错、复制账号权限不够(需要 REPLICATION SLAVE)、主库 max_connections 满了拒绝连接。请求类:从库要的 binlog 文件在主库已经被过期清理——典型场景是"从库断开太久再回来"或者"用了一个旧位点搭从库",报错会提示找不到 binlog.00000X。处理方式:连接类修配置,请求类只能重新做全备再搭。
- 迭问4:SQL 线程 No 常见原因? → 答:绝大多数是回放冲突——从库被直接写入过数据,主库日志重放时撞上"记录已存在"或"记录不存在"。处理原则:以主库为准修复从库冲突数据(删掉从库多出来的行等)再重启 SQL 线程。根治手段是制度加技术的双重防线:从库设 read_only 加 super_read_only(防止有 SUPER 权限的账号也写入),权限上只发放只读账号,"从库绝不直写"写进规范。这是 3.23 案例里那条经典故障的原型。
- 追问5(深挖):传统异步会不会不一致?怎么兜底? → 答:会。异步复制下主库提交完成即返回成功,从库还没收到时主库宕机,切换后最新事务就丢了。兜底两层:技术上上半同步复制,至少等一个从库确认收到 binlog;工程上定期做数据校验(percona 的 pt-table-checksum 类工具或定期备份比对),并保证备份加 binlog 能重建任意时间点。云上主备(移动云)由云侧托管同步策略,我在控制台关注复制延迟指标。
关联话术:"讲完 MySQL 标准模型我会主动做一次知识迁移:'项目一银行的 Vastbase 一主一备,原理是同一层的——也是日志传送加重放,只是它传的是物理 WAL 日志流,MySQL 是逻辑 binlog。我两个都实际部署过,所以对"主备复制"的理解不只是背一套线程名字。'——这句迁移是我的差异化答法。"
实操模板(主从搭建步骤,可默写):
sql
-- 主库
grant replication slave on *.* to 'repl'@'10.0.x.%' identified by 'xxx';
-- my.cnf: log_bin=on server_id=1
-- 从库: server_id=2; 导入全备后:
change master to
master_host='主库IP', master_user='repl', master_password='xxx',
master_log_file='binlog.000005', master_log_pos=1234; -- GTID则 master_auto_position=1
start slave;
show slave status\G -- 双Yes + 延迟03.5 主从延迟:原因、监控与处理 【理解】
标准回答:延迟的度量指标是 Seconds_Behind_Master,理想值为 0。原因我按主库侧和从库侧分。主库侧:大事务和慢 SQL——一个跑十分钟的大事务,从库 SQL 线程重放也要接近十分钟;锁等待让主库的提交串行化。从库侧:最本质的是"从库单个 SQL 线程串行回放"这一天生瓶颈,主库可以几百连接并发写,从库只有一个线程在追;其次从库机器配置差、从库还扛着备份和大查询拖慢回放、跨机房网络抖动。
处理对策四条:拆大事务、优化慢 SQL 和索引,让主库产生的事件变小变快;开并行复制——5.7 按事务组并行(slave_parallel_workers),8.0 的 writeset 方案按写集依赖并发更彻底;从库与主库同规格,把备份和报表类查询分到专门的从库,别让消费方和生产者抢资源;监控上对比 Master_Log_File/Read_Master_Log_Pos 与 Relay_Master_Log_File/Exec_Master_Log_Pos 的位置差距。业务影响要会讲:读写分离场景下,延迟的直接症状是"下单成功后立刻查询查不到"。
追问链:
- 追问1:下单后马上查询查不到(读写分离)怎么解? → 答:两个层面。数据库层面:上半同步复制,把"从库没收到就提交"的概率压低,但半同步退化时仍可能丢。工程层面更常用:应用做"写后读走主库"——写操作后的一小段时间内(或同一请求内)的读强制路由到主库,牺牲一点主库压力换一致性。我会把两个方案都说,并强调"绝大多数团队选工程方案",因为简单可控——这体现我不只是 DBA 视角。
- 迭问2:什么是延迟从库?解决什么? → 答:延迟从库是让从库的 SQL 线程故意延迟 N 小时再回放(CHANGE MASTER TO MASTER_DELAY=N)。它专治"逻辑误删":主库上午十点误 drop 了表,延迟 4 小时的从库此时还没执行到那条语句——立即停它的 SQL 线程、跳过误操作位点、把表数据导出回灌主库。和它互补的是"物理损坏靠主备加备份"。两类风险两套预案,把延迟从库讲成"误操作保险丝"最形象。
关联话术:"移动云云 MySQL 主备,我在控制台关注复制延迟指标并把告警接入统一告警通道;应用侧'为什么刚写入的数据在只读端查不到'这类咨询我处理过多次,用这套语言给开发解释延迟成因和'写后读走主库'的方案——把 DBA 知识用到应用协同上,是我讲这题的定位。"
3.6 mysqldump vs XtraBackup 【必背】
标准回答:一句话定性:mysqldump 是逻辑备份,XtraBackup 是物理备份。mysqldump 把库导出成 SQL 文本:优点是跨版本跨平台、能精确到单库单表导出、文本可读可编辑;缺点是数据量大时导出和恢复都慢——恢复本质是重放一遍 SQL。生产参数组合要背:--single-transaction 对 InnoDB 建立一致性快照读实现不锁表、--master-data=2 把 binlog 位点记进备份文件(搭建从库和增量恢复的锚点)、-A 全库 -R 存储过程 --triggers 触发器。
XtraBackup 走物理路线:直接拷贝 InnoDB 的 ibd 数据文件,同时持续抓取备份期间产生的 redo,恢复时用 prepare 阶段应用 redo 前滚、undo 回滚,把拷来的"不一致文件集合"变成一致性可启动的库。它的三个优势:全量快(拷文件而已)、支持基于 LSN 的增量备份、备份期间的数据变更也能进入备份。
两工具的经典对比题必须会:23:00 开始备份 23:30 结束,mysqldump 理论上只能恢复到 23:00 的快照点,之后靠 binlog 补;XtraBackup 能恢复到 23:30(含备份期间的 redo),之后同样补 binlog。
追问链:
- 追问1:mysqldump 是热备吗? → 答:严格说是"快照备":--single-transaction 让它在一致性快照上读,不阻塞业务读写,但备份开始之后的新写入不在这个备份里,要靠 binlog 追。真正意义上的热备——备份过程中产生的数据也持续进入备份集——是 XtraBackup 的物理方式(边拷边记 redo)。所以精确的表述是:mysqldump 是"不锁表的一致性快照备份",XtraBackup 是"接近热备的物理备份"。面试里把这个措辞讲精确,比直接答"是热备"高一个层次。
- 迭问2:XtraBackup 增量备份原理? → 答:每次全备完成时记录一个 LSN(日志序列号)位置;增量备份只拷贝"上一次备份的 LSN 之后被修改过的数据页",同时把备份期间新产生的 redo 也记下来。恢复有个高频考点:增量备份不能独立恢复,必须先回到全备的基础上合并(全备 apply-log 时不做回滚只前滚,再依次合并增量),最后统一 prepare 成一致状态。顺序错了或漏了某层增量,数据就不完整——这个细节是面试官爱挖的点。
- 迭问3:23:00-23:30 备份完成,两工具理论上各能恢复到几点? → 答:mysqldump 恢复到 23:00——它读到的是发起时刻的一致性快照;XtraBackup 恢复到 23:30——prepare 时应用了备份期间持续抓取的 redo,最后一刻的数据状态被保留。两者之后的时间窗都要靠 binlog 按位点重放补齐。这道题考的就是"备份期间的数据进没进备份集",把机制讲清比背结论重要。
- 迭问4(深挖):单库 30G、200G、1T 分别怎么备? → 答:我按三档策略答:30G 以内,每天 mysqldump 全量加 binlog 留 3 到 7 天,简单可靠;30 到 200G,每天 XtraBackup 全量加 binlog,物理备份窗口短;200G 以上,每周一次全量加每日增量(XtraBackup 增量)加 binlog 留 7 到 15 天,并且备份任务放到从库上执行避免影响主库。三档的共同点是都有 binlog 兜底和恢复演练——数据量越大,演练越重要,因为 RTO 直接由数据量和演练熟练度决定。
关联话术:"云 MySQL 的自动备份我配置的是'自动全备 + binlog + 保留 7 天'组合,并在控制台做过恢复到时间点的验证;两个工具的手工全流程(含 XtraBackup 增量合并恢复)在课程实验里完整跑过。这题我可以把'备份窗口、恢复目标、策略分层'三个维度一起讲,是从理论到落地的完整链路。"
实操模板:
bash
# mysqldump 全量(InnoDB不锁表+记录位点)
mysqldump -uroot -p'xxx' -A -R --triggers --single-transaction \
--master-data=2 --flush-logs | gzip > /data/backup/full_$(date +%F).sql.gz
# XtraBackup
innobackupex --user=root --password=xxx /data/xbk/full # 全量
innobackupex --apply-log /data/xbk/full/2026-10-24_02-00-00/ # 恢复前prepare
# 恢复: 全备导入 -> 按位点截取binlog重放
mysql -uroot -p < full.sql
mysqlbinlog --start-position=记录位点 binlog.000006 | mysql -uroot -p3.7 备份策略设计与恢复演练 【必背】
标准回答:我的备份策略模板是三层结构:全量、增量、恢复演练。全量层:小库每日 mysqldump、大库每日或每周 XtraBackup;增量层:binlog 是普适的增量,保留 3 到 7 天,重要系统 7 到 15 天——依据是磁盘成本和"最多要往回追多久"的业务要求,大库再叠加 XtraBackup 每日增量。实施细节四条:备份任务放从库跑、时间选凌晨低峰、crontab 调度加日志留痕加失败告警(脚本见 2.12 模板二)、find -mtime +N 滚动清理防止备份盘被自己撑爆。
第三层"恢复演练"是我特别强调的:定期把全备导入测试库、用 mysqlbinlog 从位点截取增量重放、核对行数和抽查数据——没演练过的备份等于没有备份,因为你不知道它能不能恢复、要恢复多久。误操作恢复的标准三步也要背:测试库恢复最近全备 → 解析 binlog 把误操作之前的变更截取出来(跳过误操作语句)→ 把误伤表的数据导出回灌生产。
追问链:
- 迭问1:8 点全备、9 点误 drop 一张小表、有 binlog,怎么恢复? → 答:四步:在测试库恢复 8 点的全备;用 mysqlbinlog 解析 8 点到 9 点的日志,按表名过滤出这张表的变更、跳过那条 drop;把这段增量在测试库重放,得到 9 点误删前一刻的表状态;从测试库导出该表(mysqldump 单表或 insert 语句)回灌生产。小表整个过程半小时级。关键点有两个:恢复动作全部在测试库做、生产只接受最终回灌;drop 之后新写入要评估冲突——恢复前先锁定该表操作窗口。
- 迭问2:50G 全备里误删一张 10M 的表,怎么快速恢复? → 答:核心思路是"只动那张表"而不是整库重放。从全备文件里抽出该表的建表语句和数据段(备份是文本 SQL,用 sed/awk 按表名分段导出,或导入时临时库只留这张表);再从 binlog 里截取该表在全备之后到误删前的增量;两部分合起来回灌。整库导入 50G 要几小时,单表方式十几分钟——这就是逻辑备份"可拆"的优势,也是这题想考的点。
- 迭问3:物理损坏和逻辑损坏分别靠什么兜底? → 答:两套预案对应两类风险。物理损坏——断电文件损坏、磁盘坏、误删数据文件——靠主备复制或高可用切到备库,加物理备份(XtraBackup)重建,属于"基础设施冗余"范畴。逻辑损坏——drop、truncate、delete 忘加 where——主备帮不了你,因为错误会被忠实地复制到备库,靠的是 binlog 按时间点恢复或延迟从库。答这题时把"高可用不是备份"这个误区点破,面试官一般会很认同。
- 迭问4(深挖):RPO/RTO 怎么设计的? → 答:RPO 是最多丢多少数据,由 binlog 刷盘策略(双一配置)和备份频率决定——双一加 binlog 保留 7 天,理论 RPO 接近零;RTO 是多久能恢复,由数据量、备份方式(逻辑恢复慢物理恢复快)和演练熟练度决定——所以定期演练本质上就是在压缩 RTO。用 RPO/RTO 这套度量语言讲备份,能把"备份策略"从操作题提升到架构题的高度,这也是我答这类题的框架。
关联话术:"备份方法论我跨组件复用:项目二云数据库是'自动全备 + binlog + 7 天保留 + 控制台恢复验证';同一套思想我还用在 K8s 上——etcd 定期 snapshot save 快照到监控节点、集群证书提前 30 天续期检查,都是'备份 + 演练 + 规范'的三件套。简历运维阶段职责里'制定 etcd 快照备份、故障切换演练等运维规范'写的就是这件事,数据库和集群的备份管理在我这里是同一套方法论。"
3.8 慢查询定位链路:slow_log → EXPLAIN → 索引 【必背】
标准回答:慢查询优化我的固定链路四步。第一步开慢日志:slow_query_log=ON、long_query_time=1 秒(按业务定)、log_queries_not_using_indexes=ON 把没走索引的查询也记录,日志落在 slow.log。第二步分析聚合:mysqldumpslow 或 pt-query-digest 按"执行总耗时、执行次数"排序,找出 TOP SQL——次数多但单次快的也要关注,总量同样吃人。
第三步 explain 看执行计划,四个重点字段:type 访问类型从好到坏 system、const、eq_ref、ref、range、index、all,出现 all 全表扫描就是重点优化对象,生产底线是 range;key 实际使用的索引;rows 预估扫描行数;Extra 里 Using filesort(额外排序)和 Using temporary(临时表)都是坏信号,Using index 是覆盖索引的好信号。
第四步优化三板斧:建或改索引——where、order by、join on 的列,联合索引按最左前缀设计;改写 SQL——避免 select *、拆大查询、减少回表;架构层——加缓存或读写分离。预防机制是 SQL 上线前过 explain 加审核流程。
追问链:
- 迭问1:SQL 昨天快今天突然慢,什么原因? → 答:三种高频原因:第一统计信息过旧,优化器基于过期统计估错行数选错索引,处理是 analyze table 刷新;第二数据量增长跨过临界点,原来的执行计划成本结构变了;第三缓存层失效或被挤出,原来命中缓存的查询直接打到库。排查动作:拿这条 SQL 跑 explain,和它快的时候的执行计划对比,看 type 和 key 有没有变化——计划变了查统计信息,计划没变查数据量和缓存,两条路一分开就清楚了。
- 迭问2:数据库 CPU 爆满排查思路? → 答:分层下钻:先
show full processlist看会话都在干什么——大量相同的 SQL 在跑就是慢 SQL 拖的,逐条 kill 止血;抓出嫌疑 SQL 后 explain 分析建索引或改写;如果是锁等待就看 innodb_row_lock 相关状态。OS 层配合 top -Hp 定位 mysqld 里最忙的线程,MySQL 8.0 还能按 thread 性能表关联。应急顺序永远是"先 kill 止血保住服务,再优化根治"——这个顺序说清楚,面试官就知道你处理过生产。 - 迭问3:表加了索引还是慢? → 答:查三个方向:第一条件列是否符合联合索引最左前缀,缺了最左列整个索引用不上;第二是否踩了索引失效写法——对索引列做函数运算、隐式类型转换、like 左模糊,见 3.9 的失效清单;第三基数问题,列区分度太低(比如性别列),优化器算出走索引不如全表扫,索引建了也不选。再加一个:统计信息过旧导致选错计划,analyze table 修复。加索引不是万能药,要确认它"被用上了"才算数。
- 迭问4(深挖):EXPLAIN 里 type 等级背一下? → 答:从最优到最差:system(系统表单行)> const(主键或唯一键等值,最多一行)> eq_ref(join 时按主键/唯一键匹配,每次一行)> ref(普通二级索引等值)> range(索引范围扫描,between、>、<)> index(扫全索引树,比全表略好)> all(全表扫描)。生产的上线标准我按"至少 range,禁止 all"来定——除了极小的配置表可以容忍 all。背等级不难,能说出"我拿它当上线卡点"才是实践者的话。
关联话术:"慢查询八股我结合云上的工具链讲成闭环:项目二配了数据库审计服务,异常 SQL 从审计侧先暴露,再用慢日志确认、explain 优化——'发现问题、定位问题、解决问题'的工具链我是在云环境完整走过的,这套组合拳是我讲数据库运维视野的素材。"
实操模板:
sql
-- my.cnf: slow_query_log=ON long_query_time=1 log_queries_not_using_indexes=ON
show variables like 'slow%';
explain select * from orders where user_id=100 and status=1;
-- 建(user_id,status)联合索引命中最左前缀bash
mysqldumpslow -s t -t 10 /data/mysql/slow.log # 按总耗时TOP103.9 索引类型与失效场景 【必背】
标准回答:索引先讲结构再讲类型。InnoDB 索引是 B+ 树:非叶子节点只存键做路由,叶子节点存数据且之间有双向指针,所以等值和范围查询都高效;树非常"矮胖",千万级数据三四层 IO 就能定位,这是它胜过二叉树和哈希的根本原因。类型五类:主键/聚簇索引,叶子直接存整行数据;辅助/二级索引,叶子存主键值,查完要回聚簇索引取整行(回表);联合索引,多列建一棵树,遵守最左前缀原则;唯一索引、前缀索引(长字符串只索引前 N 位省空间)。
覆盖索引是个重要概念:查询的列全部包含在索引里,免回表,explain 的 Extra 显示 Using index——这是索引设计的优化目标之一。失效八大场景必须全背:① 对索引列做函数或运算;② 隐式类型转换(字符串列传数字);③ like 左模糊 '%xx';④ <>、!=、not in;⑤ or 连接了无索引列;⑥ 违反最左前缀;⑦ 结果集占比太大优化器放弃索引;⑧ 统计信息过旧选错计划。
追问链:
- 迭问1:什么是回表?怎么减少? → 答:回表的过程:辅助索引的叶子只存"索引列值 + 主键值",用二级索引查到主键后,还要拿主键去聚簇索引树再查一次取整行数据——这就是回表,多一次树的 IO。减少回表的手段:设计联合索引把 where 条件列和 select 的列都覆盖进去,形成覆盖索引,整个查询在索引树内完成,Extra 显示 Using index;或者按查询模式精简 select 列。高频查询用覆盖索引优化,是我给开发做 SQL 评审时的常规建议。
- 迭问2:联合索引 (a,b,c) 哪些查询能用上? → 答:按最左前缀连续匹配的原则判断:where a=1 完整用上第一列;where a=1 and b=2 用上两列;where a=1 and b=2 and c=3 三列全用。where b=1 用不上——缺了最左列 a,索引树是先按 a 排序再按 b 排的,跳过 a 无法定位。where a=1 and c=2 只能用 a,c 在索引里够不着(中断后不连续)。这条规则决定了联合索引的列顺序设计:最常用作等值过滤、区分度最高的列放最左。
- 迭问3:建索引的规范? → 答:我的规范清单:每张表必须有主键(InnoDB 没有显式主键会找唯一索引、再不行生成隐藏 row_id,不可控);where、order by、join on 涉及的列建索引;联合索引把区分度高的等值列放最左;长字符串用前缀索引;不建冗余索引——已有 (a,b) 再建 (a) 就是纯浪费,还要吃写放大;生产大表加索引避开业务高峰,用 online DDL 方式避免锁表。规范的本质是"索引加速读但拖慢写",读写要平衡。
- 迭问4(深挖):为什么用 B+ 树不用 hash/二叉树? → 答:对比三种结构:哈希索引等值查找 O(1) 最快,但不支持范围查询和排序——数据库大量场景是 between、order by,哈希直接出局;二叉树和红黑树每个节点只有两路,千万数据树高几十层,每层一次磁盘 IO 不可接受;B+ 树每个节点是"页"(16K)能存大量键,树高控制在三四层,且叶子双向链表天然支持范围扫描。所以选型逻辑是"为磁盘 IO 而生"——这句话能把结构设计的本质点出来。
关联话术:"失效场景里我主答三个高频坑:隐式类型转换、like 左模糊、最左前缀——这三个是开发找我排查慢 SQL 时真实遇到最多的形态(发现入口是云数据库审计加慢日志)。我能各举一个改法:字符串条件加引号、业务改右模糊或走搜索引擎、联合索引列序重排——有场景有解法,这题就立住了。"
3.10 事务 ACID 与隔离级别 【必背】
标准回答:ACID 四个特性我按"谁保证的"来讲——这是比背定义高一档的答法:原子性 Atomicity,事务内的操作要么全做要么全不做,靠 undo log 回滚实现;一致性 Consistency,数据从一个合法状态迁移到另一个合法状态,它是最终目的,由原子性、隔离性、持久性共同保障;隔离性 Isolation,并发事务互不干扰,靠隔离级别加 MVCC 加锁实现;持久性 Durability,提交成功的数据不因宕机丢失,靠 redo log 的 WAL 机制实现。
隔离级别四级从低到高:读未提交 RU——会脏读,能读到别人未提交又回滚的数据;读已提交 RC——防脏读,但存在不可重复读(同事务两次读同一行值不同);可重复读 RR——MySQL 默认,防脏读和不可重复读,InnoDB 靠 MVCC 加 next-key 锁基本防住幻读;串行化 SE——完全隔离但并发性能最差。三个读异常的定义要能随口区分:脏读读未提交、不可重复读是值变了(update)、幻读是行数变了(insert)。
追问链:
- 迭问1:MySQL 默认隔离级别?为什么? → 答:默认 RR。原因:InnoDB 在 RR 级别用 MVCC 保证一致性读不复杂数据,用 next-key lock(记录锁加间隙锁)在当前读场景锁住范围防止幻读,在隔离性和并发之间拿到了很好的平衡,对主从复制(binlog 的 row 格式)也友好。对比要会:Oracle 和 PostgreSQL 默认 RC,从它们迁移到 MySQL 的应用要注意快照读行为的差异——同一次事务里两次读的结果在 RR 下是稳定的、RC 下可能不同,应用逻辑依赖这一点时会出问题。
- 迭问2:MVCC 是什么? → 答:多版本并发控制。实现三要素:每行记录有隐藏列(最近修改它的事务 ID 和指向 undo 的回滚指针);undo 链保存行的历史版本;读时按"快照"判断哪个版本对当前事务可见。效果是读写互不阻塞——普通 select 走快照读不申请行锁,代替了大部分加锁场景,这是 InnoDB 高并发的基石。RC 和 RR 在 MVCC 上的差异就是快照生成时机:RC 每次 select 都生成新快照(所以能看到别人的提交,不可重复读),RR 只在事务第一次 select 生成快照并沿用到底(所以可重复读)。把这两个时机讲清,MVCC 就通了。
- 迭问3:怎么验证/设置隔离级别? → 答:查当前值
select @@transaction_isolation;;会话级设置set session transaction isolation level read committed;立即对本会话生效;全局持久化写 my.cnf 的 transaction_isolation 参数重启或 global set。验证可以用两个会话开事务交替做实验——我课程实验里做过"RR 下两次读结果一致、RC 下第二次读到别人提交的新值"的对照,亲手验证过的概念答题时特别有底气。
关联话术:"这题我按'ACID 谁保证 → 四级别 → 三异常 → MVCC'的顺序一分钟讲完,层次递进不乱。还能自然接到国产库对比:'Vastbase 是 PG 系默认 RC,我实际部署过它的主备集群,迁移场景下隔离级别差异是我会主动提示开发的一个点'——一句话把八股和真实经历缝起来。"
3.11 连接数满 / CPU 高 / 数据库连不上排查 【理解】
标准回答:先说连接数满,典型报错 too many connections。排查第一步 show full processlist 看会话构成:大量 Command 是 Sleep 的,是应用连接池不释放——连接借了不还,查 wait_timeout 和应用的连接池 maxLifetime 配置;大量同一条 SQL 在 Query 状态的,是慢 SQL 把连接都占住了,走慢查询优化链路。
应急动作:按条件批量 kill 空闲长连接先止血,再评估调大 max_connections——但调大要同步核算 OS 句柄限制和内存(每个连接有线程栈开销),不能无限调。再说"数据库连不上"的排查顺序:网络和端口 telnet 3306 → 本机进程和监听 ss → 错误日志 → 是否连接数已满 → 账号主机白名单(user@'10.0.x.%' 这种限制)。
最后有个经典结合题必须会:max_connections 配了 3000 实际只能到 214——因为 OS 层 open files 限制先到顶了,要同步调 ulimit 或 systemd 的 LimitNOFILE,呼应第 1 章 1.15 的知识点。
追问链:
- 迭问1:show processlist 里 Command 列的 Sleep 和 Query? → 答:Sleep 表示连接空闲着在等新请求,Query 表示正在执行 SQL。诊断口径:Sleep 多且 Time 大,是连接池管理问题——连接长期占坑不放,对策是调 wait_timeout 让服务端主动回收空闲连接,应用侧配连接池的 maxLifetime 和 idle 超时;Query 多且 Time 长,是执行效率问题,抓 Time 最大的 SQL 走 explain 优化。两类问题的归属完全不同,一个是应用配置,一个是 SQL 质量,分清楚才不会白忙。
- 迭问2:kill 会话的命令? → 答:单杀
kill 连接ID;,ID 就是 processlist 的 Id 列。批量杀空闲连接有个实用技巧:用 information_schema 拼出 kill 语句批量执行——select concat('kill ',id,';') from information_schema.processlist where command='Sleep' and time > 600;导出结果再灌回 mysql 执行,一条龙清掉空闲超过 10 分钟的连接。这个"用 SQL 生成 SQL"的思路在批量运维里非常好用,我在面试里讲出来通常被认为有实战感。
关联话术:"云数据库的连接数上限配置、慢 SQL 拦截、审计日志这些能力我在移动云控制台都配置过;'应用连接池泄漏导致连接数缓慢上涨'这类工单,我的排查路径就是 processlist 分型 → 定位到应用配置 → 推动开发修连接池。数据库问题一半在库、一半在应用,两边都要能看,这是我做支撑的体会。"
3.12 Redis 持久化 RDB / AOF 【理解】
标准回答:Redis 的持久化两套机制解决"重启后数据还在"的问题。RDB 是定时快照:把某一时刻的全内存数据以二进制形式落盘成 dump.rdb,触发方式 save(主进程做,阻塞一切,生产禁用)和 bgsave(fork 子进程后台做)。优点是文件紧凑、恢复时直接加载二进制非常快;缺点是两次快照之间的数据在宕机时丢失——快照间隔就是丢失窗口。AOF 是命令日志:把每条写命令追加记录到文件,重启时重放命令恢复状态。
刷盘策略三档:always 每条命令都 fsync 最安全但最慢、everysec 每秒刷一次最多丢一秒(推荐默认)、no 交给 OS 不可控。AOF 的代价是文件越来越大、恢复越来越慢,靠 AOF 重写(bgrewriteaof)按当前数据状态生成最小命令集瘦身。
4.0 之后有混合持久化:重写时先写 RDB 格式的全量头、再追加 AOF 增量,恢复速度和数据安全兼得,是现在的生产主流。选型口径:纯缓存场景可以只开 RDB 甚至不持久化(丢了回源预热即可);当存储用必须 AOF 或混合。
追问链:
- 迭问1:bgsave 时还能写吗?fork 会不会卡? → 答:能写。bgsave fork 出子进程后,依靠写时复制 COW——子进程看到的是 fork 瞬间的内存快照,父进程继续处理写请求,修改的页会复制出新页给父进程,子进程照旧写旧页。但 fork 本身有一瞬间的停顿:内核要复制页表,实例越大页表越大,大实例 fork 停顿可达几十上百毫秒,监控指标是 latest_fork_usec。所以大内存实例要评估这个停顿对延迟敏感业务的影响——这是我在课程实验里测过并有数字体感的点。
- 迭问2:AOF 文件损坏怎么办? → 答:典型场景是写 AOF 时宕机,最后一条命令写了一半,重启加载报错。处理用官方工具 redis-check-aof --fix,它会定位损坏位置并把尾部不完整的部分截掉,保住前面完整的命令。代价是截断点之后的少量写操作丢失——这正好说明恢复演练的必要性:AOF 损坏怎么修、修完丢多少,都应该在演练里预演过,而不是事故现场第一次见。
- 迭问3:RDB 和 AOF 谁优先? → 答:两者都开时,重启优先加载 AOF——因为它记录得更完整,RDB 可能更旧。但答这题我习惯把问题拉回定位:Redis 在架构里是缓存还是存储决定了策略——缓存定位丢了能从 MySQL 回源重建,RDB 足够甚至不持久化;存储定位才必须 AOF/混合。我在项目里两种定位都经历过:银行项目 Redis 5.0.3 是缓存定位开的 RDB;这样答体现的是"按业务定策略"的思路而不是背优先级。
关联话术:"项目一银行现场我源码编译部署过 Redis 5.0.3——make、bind 0.0.0.0、daemonize yes 这套参数是部署指南里的固定内容,当时定位是数币平台的会话和缓存,RDB 就够;项目二移动云用的是云 Redis 双机热备,持久化策略由云侧托管。两个项目两种定位、两种策略,'为什么不一样'我讲得清,这就是真实经历的含金量。"
3.13 Redis 主从 + 哨兵原理与切换 【必背】
标准回答:先讲主从复制:从库配置 slaveof 主IP 端口(新版本 replicaof)发起,流程是:从库首次连接 → 主库执行 bgsave 生成 RDB 发给从库做全量同步 → 同步期间主库新产生的写命令暂存在缓冲区、随后以命令流持续发送 → 之后主库每条写命令实时广播给从库。断线重连用 PSYNC 做部分重同步:双方维护复制偏移量和 backlog 缓冲,断开时间短、偏移量还在 backlog 里,就只补差量,不全量重来;差太远才退化为全量。
再讲哨兵 Sentinel:独立部署的监控进程,建议至少 3 个节点奇数部署,四大职能——监控(持续 ping 主从及彼此)、通知、自动故障转移、配置中心(客户端通过哨兵拿当前主库地址)。
切换流程背关键词链:单哨兵 ping 主库超时判"主观下线 sdown"→ 询问其他哨兵,达到 quorum 法定人数同意判"客观下线 odown"→ 哨兵间 Raft 思想多数派选出 leader 执行切换 → leader 按规则挑新主(过滤下线的、replica-priority 优先级高优先、复制偏移量大优先、runid 小优先)→ 其余从库改挂新主 → 旧主恢复后自动降为从。客户端连哨兵集群而非直连主库,切换后自动感知,应用无感。
追问链:
- 迭问1:主从复制是全量还是增量? → 答:分阶段:第一次同步必然全量(RDB 快照加命令流补齐);稳定期是增量命令流——主库每条写命令实时传播;断线重连先尝试 PSYNC 部分重同步(按偏移量补差),只有 backlog 覆盖不住断开窗口时才重新全量。所以准确的说法是"全量打底、增量跟随、断线按需",三个阶段的状态和触发条件都能说清,这题就完整了。
- 迭问2:为什么哨兵至少 3 个且奇数? → 答:因为哨兵的两个关键决策都依赖多数派投票:判客观下线要 quorum 个哨兵同意,选执行切换的 leader 要多数派选举。2 个哨兵挂 1 个就只剩 1 个,无法形成任何多数派,故障转移瘫痪,容错能力和 1 个一样;3 个容 1 个、5 个容 2 个——多一个偶数节点只增加成本不增加容错。这个数学和 etcd 副本数、K8s 控制面副本数是同一个道理,我面试时会把这三者串起来讲,展示的是对"分布式多数派"的通用理解而不是孤立的 Redis 知识。
- 迭问3:主从和哨兵和集群的区别? → 答:三级递进各解决一个问题:主从解决读扩展和数据冗余,但主挂了要人工切换,有窗口;哨兵在主从之上加自动故障转移,主库挂了秒级切到从库,但写入容量还是单主的上限;Cluster 集群再加数据分片,16384 个槽位分布到多个主分片,写入容量和存储容量都能横向扩。选型按量级走:读多写少主从加哨兵足够;数据量或写吞吐超单机再上 Cluster。我经历的两个项目都在前两级(自建单实例/云主备),Cluster 属于"知道什么时候该上、当前为什么不用"的层——这个判断本身也是考点。
- 迭问4(深挖):哨兵切换会不会丢数据? → 答:会,要主动讲清这个边界。主从复制是异步的:主库写入成功即返回客户端,还没来得及传给从库时主库宕机,切换后这部分写入就丢了;AOF everysec 也有最多一秒的窗口。所以 Redis 的定位是"高性能低延迟、允许极小概率丢失"的场景,要求强一致就不该拿 Redis 当存储,要么接受这个边界要么用等待同步的部署模式。能主动讲出组件的"不能",比把原理背得滚瓜烂熟更让面试官放心。
关联话术:"简历写'熟悉 Redis 主备/哨兵架构',我的支撑材料是三层:银行项目自建 Redis 5.0.3(源码编译、缓存定位、RDB);移动云云 Redis 双机热备(云侧托管哨兵逻辑,我关注主从状态和连接数);哨兵三节点部署加主库宕机自动切换在课程实验里完整验证过——三层按'生产、云上、实验'各就各位,我答的时候诚实分层,反而每一层都站得住。"
实操模板:
bash
# 主从: 从库 redis.conf
replicaof 主IP 6379
masterauth 密码 # 主库开了requirepass时
# 哨兵 sentinel.conf(三节点各一份)
port 26379
sentinel monitor mymaster 主IP 6379 2 # quorum=2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
# 验证
redis-cli -p 26379 sentinel get-master-addr-by-name mymaster # 查当前主
redis-cli -p 26379 sentinel masters # 看状态3.14 Redis Cluster 分片概念 【理解】
标准回答:Redis Cluster 是官方的分布式方案,核心设计是哈希槽分片:整个键空间划成 16384 个 slot,每个主分片节点负责一段;写 key 时对 key 做 CRC16 校验再对 16384 取模,算出槽位号就知道归哪个节点管。客户端可以连任意节点,找错了会被 MOVED 响应重定向到正确节点,智能客户端会本地缓存槽位映射表直连。
高可用内建:每个主分片配从节点,主挂了剩余主节点投票(多数派)让它的从顶上,不需要独立的哨兵进程——去中心化设计。价值是突破单机内存上限和单主写入上限,横向扩容;代价也明确:多 key 操作和事务跨槽受限(要 hash tag 把相关 key 固定到同槽)、运维复杂度上一个台阶。
我的选型观:规模不大时主从加哨兵够用且好运维,数据量或写压力到单机瓶颈再上 Cluster——"知道什么时候该换"和"会用"同样重要。
追问链:
- 迭问1:槽位怎么迁移扩容? → 答:流程是:新节点加入集群 → 用 redis-cli --cluster reshard 把一部分槽从现有主节点迁到新节点 → 迁移期间源节点把该槽标记为 migrating、目标标记为 importing,逐个 key 迁移,访问时源节点还能正常响应或返回 ASK 重定向到新节点 → 迁完后槽的归属更新。要点是迁移过程保证不丢写。这个流程我知道原理和命令形态,生产上没手工做过大规模 reshard——如实说,当前业务量也没到需要分片的程度。
关联话术:"云 Redis 我用的是双机热备主备规格——业务量没到分片的必要,主备加云侧高可用已经满足;但'什么时候该上 Cluster、上了要注意什么(hash tag、多 key 限制)'这个判断框架我有。答这题的策略是展示选型思维:不为技术先进而上技术,按量级和团队运维能力定方案。"
3.15 缓存穿透 / 击穿 / 雪崩(三兄弟)【必背】
标准回答:这三个问题我每个都按"一句话定义、攻击画像、对策"讲。穿透:查询的数据在缓存和数据库里都不存在,每次请求都穿过缓存直击数据库——恶意攻击常用不存在的 id 高频请求,缓存永远帮不上忙。对策三条:缓存空值(把"不存在"也缓存起来,配短 TTL 如 60 秒)、布隆过滤器前置(把存在的 key 预先登记,一定不存在的直接拒绝)、接口层做参数合法性校验。
击穿:某个热点 key 在过期的一瞬间,大量并发同时回源查库重建缓存,DB 瞬间被这一个 key 的流量打死。对策:热点数据逻辑过期或不设 TTL(后台异步刷新)、互斥锁——只放一个请求去查库重建,其他请求短暂等待读新缓存、热点提前预热。雪崩:大量 key 同一时刻集体过期,或 Redis 实例整体宕机,请求洪峰全部压到 DB。
对策:过期时间加随机值把过期点打散、多级缓存(本地缓存加 Redis)、Redis 自身高可用(主备/哨兵/集群)、下游限流降级兜底。记忆钩子一句话:穿透是查不存在的、击穿是热点单个过期、雪崩是批量过期或整挂。
追问链:
- 迭问1:布隆过滤器原理?为什么会误判? → 答:结构是"一个位数组加多个哈希函数"。写入时把 key 用 k 个哈希函数算出 k 个位置置为 1;查询时算同样 k 个位置——只要有任何一位是 0,这个 key 一定没出现过,直接拒绝;全是 1 才认为"可能存在"放行去查库。误判的来源是哈希碰撞:不同的 key 可能哈希到相同位,把不存在误判为可能存在——但方向是安全的,只会多放行不会错杀。局限还有两个:不能删除元素(位数组不支持退位,计数布隆过滤器可以)、误判率随装载率上升。这套"一定不存在/可能存在"的语义答清楚,原理就到位了。
- 迭问2:互斥锁重建缓存怎么实现? → 答:用 setnx 的原子性抢锁:请求发现缓存 miss 后,
set lock:key 1 nx ex 10尝试抢锁并设过期防死锁——抢到的那个请求去查 DB、回写缓存、删锁;没抢到的 sleep 几百毫秒重试读缓存。效果是同一个 key 的回源并发收敛为 1,DB 只被打一次。两个工程细节要提:锁必须带过期时间(持有者崩溃时防死锁)、等待方要有重试上限(避免无限等)。这是击穿的标配套路,我能在白板上画出时序。 - 迭问3:缓存和数据库一致性怎么保? → 答:主流方案 Cache Aside 旁路缓存:读——先读缓存,miss 则查 DB 并回填;写——先更新 DB,再删除缓存(不是更新缓存,删更简单且避免并发写导致的脏数据)。这个方案在极端并发下仍有小概率不一致窗口,要求更高的场景有两条路:分布式锁串行化、或订阅 binlog(canal 类工具)异步失效缓存——把一致性从应用代码挪到数据链路。我按业务一致性要求选档:多数业务 Cache Aside 够,金融敏感场景再上订阅方案——分层答比"保证一致"的绝对化说法专业。
关联话术:"云 Redis 场景里我配合开发处理过缓存类问题,能按这三种画像归因:现象是'查不到的数据也慢'指向穿透、'某个热点接口定时抖动'指向击穿、'整批接口同时抖'指向雪崩。'过期时间加随机值'这种零成本对策是我们直接落地的;布隆过滤器这类改造按业务优先级排期。工具是云的,方法论是通用的——这是我答中间件类问题的定位。"
3.16 内存淘汰策略与日常命令 【理解】
标准回答:Redis 内存达到 maxmemory 上限后,按 maxmemory-policy 决定行为,8 种策略按两个维度记:淘汰范围(全键 allkeys / 仅带过期时间的 volatile)和淘汰算法(lru 最近最少使用 / lfu 按访问频率 / random 随机 / ttl 挑快过期的),再加一个 noeviction 默认策略——不淘汰、写操作直接报错。纯缓存场景推荐 allkeys-lru 或 8.0 的 allkeys-lfu,把最冷的数据挤出去。
日常运维命令是我的巡检清单:dbsize 看键规模;info memory 看 used_memory_human 实际用量和 mem_fragmentation_ratio 碎片率;info replication 看主从角色和偏移量;ttl key 看过期;遍历键必须用 scan 游标分批——生产严禁 keys *,它是全量阻塞主线程的操作,大库一敲整个 Redis 冻住;config get/set 在线改参数;slowlog get 10 看慢命令;client list 看连接。
这套命令在银行项目巡检 Redis 时是每天的功课。
追问链:
- 迭问1:为什么生产禁用 keys *? → 答:keys 做的是全键空间遍历,复杂度 O(N) 且在主线程同步执行——遍历期间不能处理任何其他命令,键多的话 Redis 会卡顿几秒到几十秒,对业务等于一次微型故障。替代方案是 scan:基于游标的增量迭代,每次只取一小批就返回,把总工作量摊到多次调用里,期间其他请求正常处理。代价是 scan 在遍历期间对增量修改的语义是"不保证完整不重复",巡检场景完全可接受。这个对比是"命令选型影响可用性"的最好例子。
- 迭问2:内存碎片率怎么看、多高算异常? → 答:
info memory里的 mem_fragmentation_ratio 等于 used_memory_rss(操作系统视角的物理内存)除以 used_memory(Redis 逻辑用量)。1.0 到 1.5 之间正常—— allocator 分配粒度带来的合理开销;持续大于 1.5 说明碎片明显,常见于频繁创建销毁不同大小的键值;低于 1 说明用了 swap,要立刻警惕。处理手段:4.0 以上开启 activedefrag 主动碎片整理(在线进行),或者维护窗口重启进程彻底回收。把">1.5 碎片、<1 换页"这两个数字判断说清楚,这题就是满分形态。
关联话术:"info 命令族是我巡检 Redis 的入口——项目一职责原文里就有'运用 redis-cli、info 命令掌握资源使用情况'这条:每天看内存用量、碎片率、连接数、主从偏移,异常项记进巡检报表。淘汰策略这类参数在云控制台配置时我核对过语义——'为什么选 allkeys-lru'对应的正是缓存定位,和 3.12 的持久化选型逻辑一脉相承。"
实操模板:
bash
redis-cli -h IP info memory | egrep 'used_memory_human|fragmentation_ratio'
redis-cli -h IP info replication # role / slave 数 / 偏移量
redis-cli -h IP --scan --pattern 'sess:*' | head # 分批扫描替代 keys*
redis-cli -h IP config get maxmemory maxmemory-policy
redis-cli -h IP slowlog get 103.17 Vastbase / OpenGauss:是什么与真实部署 【必背】
标准回答:一句话定位:Vastbase G100 是海量数据公司基于华为 openGauss 内核做的商业发行版数据库,PostgreSQL 系语法,在信创目录里承担 Oracle/MySQL 的国产替代,对鲲鹏 ARM 有原生适配——我拿到的安装包就是 kylin_v10sp1-aarch64_kunpeng 专用包,跑在麒麟 V10 加鲲鹏的环境上。
我在银行项目亲手部署过一主一备高可用集群,全流程背得出来:第一步两节点上传安装包和自动化部署包,配置 install.conf 写安装目录和 IP;第二步两节点同时执行 sh vbcluster_install.sh install.conf,关键约束是执行时间误差不能超过 10 秒,保证集群初始化握手;第三步装完 systemctl enable has dcs——HAS 是高可用组件负责监控和自动切换,DCS 是分布式配置存储,角色类似 etcd 的一致性底座;第四步验收四查:查 DCS 状态、查 HAS 状态、查数据库集群主备角色、vsql 建用户授权后用 DataStudio 远程连接测试;第五步 license 管理:自带 3 个月免费期,到期前替换 vastbase.yml 里的 license 路径,然后滚动重启 has——先一个节点重启、等它就绪后再另一个,避免双主。调优我实际改过两个参数:max_connections 从默认 100 调到 10000、开线程池 enable_thread_pool=on。
追问链:
- 迭问1:为什么选 Vastbase 不选 MySQL? → 答:我的答法是先亮角色再讲理解:"选型是华为配套体系加信创合规定的,我负责按配套表落地"——公司是华为渠道商,这个角色定位说出来反而加分。理由三条:信创目录合规要求,金融场景必须国产数据库;Vastbase 是 openGauss 生态商业版,对鲲鹏 ARM 原生适配;华为 BCS 区块链平台的配套认证体系。它是 PG 系,vsql 和 DataStudio 工具链与 PG 兼容——面试官如果顺势问 PG 和 MySQL 区别,正好接到 3.18 的对比内容,是我主动铺的路。
- 迭问2:部署踩过什么坑? → 答:两个真实坑。第一安装目录权限:自动化脚本用 vastbase 用户执行,安装目录不在 /home/vastbase 前缀下时会因为无读写权限失败——解决是提前规划目录属主,或把安装路径放进 vastbase 用户可控范围。第二 license 更换的重启方式:必须滚动重启 has,先节点 A 重启、确认就绪后再节点 B;如果两台同时重启,DCS 失去多数派可能出现双主风险。这两个坑都是我亲手排掉并写进部署指南的,讲的时候有细节有教训。
- 迭问3:主备切换怎么验证的? → 答:三层验证。先查静态:HAS 集群状态里主备角色正确(hasctl list 输出)。再演练动态:模拟主节点故障(停主库进程),观察 HAS 自动切换、备库升主、VIP 漂移到新主。最后验应用侧:应用连接串走数据库 VIP,切换后无感恢复。这套"查状态、造故障、验入口"的三段式验证和我在 K8s 上做控制面故障切换演练是同一套方法论——我在面试里会主动把两个项目的验证方法对应起来讲,体现方法论可迁移。
- 迭问4(深挖):openGauss 和 PG 什么关系? → 答:openGauss 是华为基于 PostgreSQL 早期版本演化的内核,在企业级特性上做了大量增强:线程池模型(PG 是每连接一进程,openGauss 可以线程复用,高并发下开销小——我开 enable_thread_pool 就是这个)、MOT 内存引擎、AI 调优特性等;Vastbase 再在其上做商业化、信创适配和工具链。内核级的执行器差异我理解到线程模型这一层,更深的比如优化器差异我如实说可以会后补——边界感在国产库话题上尤其重要,因为面试官可能很懂。
关联话术:"这是简历第 9 条里我能完全放开讲的部分:某银行内网环境、麒麟 V10 加鲲鹏 ARM 的真实生产部署,从上传安装包、双节点 10 秒内同步执行、HAS/DCS 自启、参数调优到 license 滚动重启,全链路是我主导做的,配套细节都是一手经验。面试官问'国产数据库你实际用过吗',我的答案不是'了解'而是'装过、调过、验收过'。"
实操模板(部署与验收命令链,可背):
bash
# 1) 两节点同时执行(误差<10s)
sh vbcluster_install.sh install.conf
# 2) 高可用组件开机自启
systemctl enable has dcs
# 3) 验收四查
systemctl status dcs && systemctl status has
/home/vastbase/has/bin/hasctl -c /home/vastbase/has/etc/vastbase.yml list # 集群主备角色
su - vastbase -c "vsql -r" # 命令行登录验证
# 4) 参数调优(hasctl edit-config 进配置)
# max_connections = 10000 enable_thread_pool = on → 保存后滚动重启has
# 5) license 更换
vi /etc/vastbase/has/etc/vastbase.yml # 改 licence 路径
systemctl restart has # 先节点A,就绪后再节点B3.18 Vastbase 与 MySQL 的运维差异 【理解】
标准回答:站在运维角度我总结了五个最相关的差异。第一客户端与语法:vsql 对应 mysql 客户端,SQL 是 PG 系——查会话用 select * from pg_stat_activity 对应 show processlist,元命令 \l 列库、\du 列用户;管理工具是 DataStudio 对应 Workbench/Navicat。
第二复制机制:openGauss 主推物理复制——主库产生 WAL 日志流,备库按页级别重放,一致性强;MySQL 主推逻辑 binlog 复制——重放 SQL 或行变更,粒度灵活。第三进程模型:openGauss 是线程池模型,连接开销小,我把 max_connections 调到 10000 就是吃这个红利;MySQL 是每连接一线程,几千连接的线程调度和栈内存就是压力,所以要盯 max_connections。
第四默认隔离级别:PG 系默认 RC,MySQL 默认 RR,迁移的应用要注意快照读行为差异。第五迁移工作量主要在开发侧:函数语法、大小写敏感行为、自增列用序列(sequence)实现这些差异,是我提示开发评估的点。
追问链:
- 迭问1:vsql 里怎么查"processlist 等价物"? → 答:
select * from pg_stat_activity——能看到每个会话的状态、等待事件、执行的 SQL;需要终结会话时用pg_terminate_backend(pid),对应 MySQL 的 kill。这两条是我背熟的日常组合:先 activity 看谁在占着、再 terminate 清理。顺带能讲一个差异:PG 系里长时间运行的 idle in transaction 会话危害大(阻碍 vacuum 回收),巡检时要专门抓 state 为 idle in transaction 且时间长的会话——这个细节体现真用过。 - 迭问2:PG 和 MySQL 怎么选型? → 答:各自优势一句话:PG 系胜在 SQL 标准兼容度高、复杂查询和分析能力强、JSON 支持和扩展生态(PostGIS 这类)丰富;MySQL 胜在互联网生态成熟、中间件和人才储备多、简单场景上手快。落到我的实际语境:信创场景 PG 系是主流路线——openGauss、Vastbase、人大金仓都是 PG 血统,我在银行项目实测部署过;互联网业务 MySQL 云服务也运维过——两边都摸过、能对比着讲,这正好是我简历第 8、9 两条技能的交叉点。
关联话术:"面试官问'国产数据库你实际用过吗',我就用这一节回答:真实部署加参数调优加与 MySQL 的对比理解。我会说:'Vastbase 我不只是装起来了——max_connections 调到 10000、线程池开启这两个参数为什么这么调、和 MySQL 每连接一线程的差异在哪,我都能讲清楚'——比只背八股的候选人多一层手上功夫。"
3.19 RocketMQ:用途与能聊口径 【了解】
标准回答:RocketMQ 是阿里开源的分布式消息队列,运维口径我先讲它解决什么问题——三个价值词:异步(下单后发条消息,积分、通知这些下游慢慢消费,主流程不等它们)、解耦(订单服务不直接调库存物流,通过 Topic 通信,谁消费谁订阅)、削峰(秒杀洪峰先入队,消费端按自己的能力匀速消费,DB 不被瞬时流量打死)。
架构名词对得上号:NameServer 是轻量注册中心存路由信息、Broker 是存储节点主从架构、Topic 和 Queue 是消息主题与队列、Producer 和 Consumer 是生产消费两端、消费者组做负载均衡消费。
我的实际经历是部署维护过移动云的 RocketMQ 5 两节点主备云实例:负责实例规格规划、内网访问配置、Topic 和消费组的创建、把连接信息交付应用;高可用和存储由云侧托管,我看监控的两个核心指标——消息堆积量和消费延迟,堆积告警时推动消费端扩容或排查消费阻塞。
追问链:
- 迭问1:消息丢了怎么办(可靠性)? → 答:我按三层保证的口径讲:生产端同步发送等 broker 确认(异步发送失败要重试);Broker 层主从同步复制加刷盘策略(同步刷盘最安全,异步刷盘性能好窗口小);消费端处理完再手动 ACK,失败走重试队列、多次失败进死信队列人工处理。云上这三层是托管项,我的职责是配置正确、告警(堆积)时推动消费端扩容或修 Bug——把"组件怎么保证"和"我怎么运维"分开说,口径就很稳。
- 迭问2:和 Kafka 的区别? → 答:Kafka 定位超高性能的日志流管道,顺序写加批量拉取,吞吐最高,适合日志采集、大数据管道这类允许少量重复的场景;RocketMQ 在业务消息特性上更全——事务消息、延迟消息、消息重试和死信队列开箱即用,适合交易类业务链路。我的口径是"业务解耦选 RocketMQ、日志管道选 Kafka",属于了解层的对比,不往存储引擎细节上深挖——被深挖就如实说这层在继续学习。
关联话术:"能聊的口径我定义为:部署过云上主备实例 + 三价值 + 认识架构图。面试被深挖内核(比如刷盘机制源码级)我的兜底话术是:'我的定位是云实例的使用和运维,规格规划、Topic 管理、堆积告警处理是我的日常;内核层的机制我理解到同步复制和刷盘策略这一层,更深的我入职后会系统补'——诚实且展示了已有的面。"
3.20 Nacos:用途与能聊口径 【了解】
标准回答:Nacos 是阿里开源的"注册中心加配置中心"二合一组件。注册中心职能:服务发现——服务实例启动时注册上来,调用方按服务名从 Nacos 拉取健康实例列表发起调用,实例下线自动摘除,微服务体系的"电话簿"。配置中心职能:配置集中托管加热更新——配置改完推送生效,应用不用重启,彻底解决"改一个配置重发一次"的痛苦。
核心概念四个:命名空间(namespace,典型按环境隔离 dev/test/prod)、分组、服务/集群/实例三级结构、配置的 dataId。健康检查两种模式对应两个一致性取向:临时实例走客户端心跳(AP 取向,可用性优先)、持久实例走服务端长连接探测(CP 取向 Raft)。
我的实际经历:部署维护过移动云的 Nacos 集群版云服务——实例规划、命名空间按环境划分、账号权限配置、把注册地址和配置导入流程交付给应用团队。
追问链:
- 迭问1:注册中心和配置中心为什么常用一个组件? → 答:因为它们的服务对象和基础设施属性相同:都是"微服务的元数据"——一个是运行时元数据(谁在线、在哪),一个是配置元数据(用什么参数),都需要高可用集群、多环境隔离、变更推送这套底座。Nacos 把两者统一在一个数据模型和部署体系里,运维成本减半。功能上等价于 Eureka 加 Apollo 的合体——这个类比是我的记忆锚点,也是快速给别人解释 Nacos 的最短路径。
- 迭问2:配置热更新怎么实现的? → 答:机制是客户端长轮询(Long Polling):客户端发起请求后服务端 hold 住不立刻返回(默认最多 30 秒),期间配置一旦变更,服务端立即返回变更的 dataId 列表,客户端再拉取新配置内容并触发本地监听回调刷新。长轮询的妙处是既接近实时的推送效果,又不需要维护服务端到客户端的长连接。原理我了解这一层,够支撑"为什么改配置秒级生效"这类追问。
关联话术:"项目二配套云服务清单里 RocketMQ 和 Nacos 都是我规划交付的——简历职责原文'负责云数据库、消息队列、注册中心…的配置管理与业务系统发布支持'。面试我按'用得好、讲得清定位'的口径聊:命名空间怎么分环境、应用怎么接入、配置怎么热更新,这些操作层的我都能讲;内核层(Raft 细节)如实说在了解层面。"
3.21 MySQL 5.7 与 8.0 的运维视角差异 【了解】
标准回答:从运维最相关的几条说。默认字符集:8.0 默认 utf8mb4,5.7 默认 latin1——新项目 5.7 必须显式设 utf8mb4,否则中文和 emoji 会踩坑。用户管理:8.0 的 create user 和 grant 分离,5.7 可以一条 grant 连建带授权;8.0 默认认证插件 caching_sha2_password,老客户端和老驱动连不上,兼容方案是建用户时显式指定 mysql_native_password。
查询缓存:8.0 删掉了查询缓存——它命中率低、维护开销大,本来就是个失败特性。索引增强:8.0 有隐藏索引(上线前灰度验证)、降序索引、函数索引。DDL:8.0 大部分加列操作 instant 秒级完成,5.7 要重建表。还有默认角色、账密过期策略这些安全增强。迁移时的检查清单:应用驱动版本、认证插件、SQL 兼容性(8.0 移除了 group by 隐式排序)。
追问链:
- 迭问1:你们用的哪个版本? → 答:云上生产是 8.0(项目二移动云 MySQL 8.0 主备),我的实验和八股练习也以 8.0 为主、5.7 做对比学习。答题时我会主动带版本意识:"比如认证插件这个坑就是 8.0 特有的,我遇到过老应用连 8.0 报认证错误"——用具体现象证明我不是只在背版本号清单。
3.22 关系型 vs 非关系型一句话 【了解】
标准回答:关系型数据库(MySQL、PG、Vastbase)的特点:强一致、事务 ACID、SQL 标准、成熟的数据模型约束,适合交易、账务这类"错一分钱都不行"的核心数据。非关系型(Redis、MongoDB、ES)的特点:超高性能、易水平扩展、schema 灵活,代价是放松一致性(最终一致),适合缓存、高频读写、全文检索这类性能敏感场景。
两者是互补不是替代:典型架构就是 MySQL 做持久化主存储、Redis 前置缓存挡读流量、ES 承担搜索——各司其职。这个组合正是我两个项目里真实用到的:数币平台是 MySQL 体系的 Vastbase 加 Redis 缓存,移动云是云 MySQL 加云 Redis 加消息队列——所以"什么时候用什么"我不只是背原则,是有架构实例支撑的。
3.24 MySQL 参数调优与 my.cnf 核心清单 【理解】
标准回答:MySQL 调优我的第一原则:先看慢日志和连接行为,再动参数——参数调优是最后的手段不是第一反应。真要调,核心参数按优先级背这份清单:innodb_buffer_pool_size 是第一参数,专用数据库机器给物理内存的 50% 到 70%,它决定了数据页命中率,一行参数对性能的影响超过其他所有参数之和;max_connections 连接上限,默认 151 太小,按业务并发评估到 500 到 2000,但要同步核算 OS 句柄(对应第 1 章 ulimit)和每连接内存开销;innodb_flush_log_at_trx_commit 和 sync_binlog 是双一标准,金融级安全双 1,性能敏感可以放宽但要明白风险;slow_query_log 加 long_query_time=1 必开——不开慢日志等于放弃排障入口;character_set_server=utf8mb4、binlog_format=row、binlog_expire_logs_seconds 保留期按备份策略对齐(我们 7 天)。
改参数的流程纪律:my.cnf 改完需要重启生效的重大参数一定安排变更窗口、改前备份配置、改后 show variables like 验证生效值。
追问链:
- 迭问1:buffer_pool 为什么是 50-70% 而不是越大越好? → 答:因为内存里不只住着 InnoDB:OS 页缓存、每个连接的线程栈和排序缓冲、临时表、还有数据库机器上可能跑的备份和监控 Agent 都要吃内存。给满了会出现"MySQL 要内存时 OS 拿不出来,触发 swap 或 OOM"的反效果。专用 DB 机器 70% 封顶、混部环境更低,同时用
show status like 'Innodb_buffer_pool_read%'的命中率验证调大是否真有收益——命中率已经 99% 以上再调大就是浪费,参数要用数据说话。 - 迭问2:除了参数还有什么调优手段? → 答:按收益从大到小排:SQL 和索引优化是第一位的(3.8/3.9),一个全表扫描靠索引消掉,收益超过任何参数;架构层读写分离、加缓存挡读流量;硬件层把数据盘换 SSD、IO 队列调优;最后才是参数微调。我的表述习惯:"参数调优是排序最后的手段"——这个排序本身就是面试官想听的工程判断。
关联话术:"云 MySQL 的参数我在控制台按这套清单核对过默认值(连接数、慢日志阈值、binlog 保留),自建实验里 my.cnf 我手写过完整版;Vastbase 那两个调优参数(max_connections 10000、线程池)也是同一逻辑——先评估瓶颈在连接数和调度开销,再精准下参数,调完都有验证动作。"
3.25 读写分离与分库分表(概念口径)【了解】
标准回答:这两个是数据库扩展性的话题,按"解决什么问题"讲。读写分离:主库扛写、从库扛读,把读流量水平分摊——适合读多写少的业务(典型互联网应用读写比 8:2 甚至更高)。实现层两种:应用层在代码里配多数据源按操作类型路由(可控性强);中间件层用 MyCat、ShardingSphere-Proxy 这类代理,应用无感知。
代价两条:主从延迟带来的"写后读不到"问题(3.5 讲过写后读走主库的解法)、以及路由层自身的可用性和运维复杂度。分库分表:当单库数据量或写入量到单机瓶颈(经验值单表几千万行、单库几 TB 级别)时,把数据按规则拆到多个库表——垂直拆按业务域(订单库、用户库),水平拆按分片键(user_id 取模、按时间范围)。带来的新问题:跨分片 join 和事务困难、分片键选择决定查询效率、全局 ID 要专门方案(雪花算法)。
我的诚实口径:这两个我按"理解原理和适用条件"答,没有生产级实施经验——移动云是云托管主备(读写分离由云侧提供只读实例能力),分库分表没到那个量级。
追问链:
- 迭问1:什么信号说明该分库分表了? → 答:三个信号叠加:单表数据量到千万级且还在快速涨,B+ 树层数变高、维护窗口内 DDL 都跑不动;写入 QPS 把主库 CPU 和 IO 推到瓶颈,读写分离已挡不住(写是单点的);备份恢复时间长得不可接受(RTO 失控)。动作顺序也要强调:先读写分离和归档历史数据,再考虑分库分表——它是最后的大招,一旦做了几乎不可逆,架构上能不分就不分。
关联话术:"面试聊这个话题我的答法是讲判断不讲实施:'我们业务量级没到分库分表,但我清楚触发的三个信号和代价——所以我的方案是云主备加只读实例,为将来留了扩展路径。'能讲清'什么时候该做'和'为什么现在不做',比硬吹做过更可信。"
3.26 数据库日常巡检清单(MySQL / Redis / Vastbase)【理解】
标准回答:数据库巡检我按三个对象各背一份清单,这是我在银行驻场期间每天执行的功课。MySQL 五看:show processlist 看会话有没有堆积和长事务;show slave status 主从双 Yes 和延迟(云上看控制台延迟指标);show variables like 'max_connections' 加当前连接数占比;慢日志增量——今天新增了几条慢 SQL;磁盘空间和增长趋势(数据目录加 binlog)。
Redis 四看:info memory 内存用量和碎片率(1.0-1.5 正常,见 3.16);info replication 主从角色和偏移量;连接数和拒绝数(rejected_connections 非零说明超过 maxclients 了);慢命令 slowlog。
Vastbase 三看:systemctl status has dcs 高可用组件健康;hasctl list 主备角色正确;会话和锁等待(pg_stat_activity 里长事务和 idle in transaction)。巡检的价值不在"看"而在"留痕和对比"——每天的快照汇成趋势,异常是从趋势里先看出来的。
实操模板(巡检命令组,可背):
bash
# MySQL
mysql -e "show processlist;" | grep -vc Sleep # 活跃会话数
mysql -e "show status like 'Threads_connected';"
# Redis
redis-cli info memory | egrep 'used_memory_human|fragmentation_ratio'
redis-cli info replication | egrep 'role|slave_io|master_repl_offset'
redis-cli info clients | egrep 'connected_clients|rejected'
# Vastbase/openGauss
systemctl is-active has dcs && su - vastbase -c "vsql -c 'select count(*) from pg_stat_activity;'"追问链:
- 迭问1:巡检发现慢 SQL 增多,你的处理流程? → 答:第一步确认影响面——是不是伴随连接数上涨、CPU 升高,判断紧急程度;第二步把新增慢 SQL 按 3.8 的链路走:mysqldumpslow 或云审计聚合排序、锁定 TOP 几条、explain 看执行计划;第三步分类处置——能加索引解决的建索引(评估锁表风险)、需要改写的反馈开发、突发的流量异常先限流止损;第四步把结论记进巡检日志形成闭环。整套动作的目标是把"发现异常"变成"当天有结论",这是我理解巡检的意义。
关联话术:"银行项目两年驻场,数据库巡检是我每天雷打不动的动作,上面对象里 Vastbase 是每天真跑、MySQL 和 Redis 的清单是同源方法论的延伸(课程实验加云上运维)。'每天巡检快照汇成趋势'这个习惯后来直接演变成我移动云的监控大盘思路——人肉巡检的每个检查项,就是后来告警规则的每条 expr。"
3.27 Vastbase / openGauss 备份恢复(概念 + 能聊口径)【了解】
标准回答:openGauss 体系的备份工具家族我按对应关系讲:gs_dump 对应 MySQL 的 mysqldump——逻辑导出库或模式,支持自定义格式;gs_restore 对应导入恢复;gs_basebackup 对应 XtraBackup 的角色——物理全量备份,拷贝数据目录加 WAL;归档模式(archive_mode)开启后 WAL 日志持续归档,配合物理备份实现 PITR 按时间点恢复——这套"物理备份加 WAL 归档"的组合和 MySQL 的"XtraBackup 加 binlog"是完全同构的思想。
我在银行项目的实际口径:部署验收阶段我负责的是集群可用性和参数调优,备份策略由客户侧的备份系统统一纳管(金融环境有集中备份平台),所以工具级操作我按"理解原理、能讲对应关系"答,不冒充做过完整的 PITR 演练。能主动讲清"PG 系用 WAL、MySQL 用 binlog,机制同构"这一点,就足以证明理解深度。
追问链:
- 迭问1:物理备份和 WAL 归档怎么配合做 PITR? → 答:原理三步:先有一个物理全备(gs_basebackup 或文件级快照);之后数据库持续把 WAL 段归档到备份存储(archive_mode 加 archive_dest);恢复时把全备还原、配置 recovery 目标时间点,重放归档的 WAL 到指定时刻——效果等于 MySQL 的"全备导入加 mysqlbinlog 按位点重放"。两个体系的共同要点:归档不能断(断档就丢恢复点)、恢复演练要定期做——这些是我在 MySQL 侧 3.7 建立的原则,同构地适用过来。
关联话术:"被问'国产库备份你做过吗',我的诚实答法:'客户环境有集中备份平台纳管,我的职责边界是集群部署验收;但备份原理我在 MySQL 侧完整实操过,PG 系的 gs_dump/gs_basebackup/WAL 归档对应关系我能讲清楚——同构的知识迁移是我学国产化栈最快的原因。'"
3.28 Redis 大 key 与热 key 治理 【理解】
标准回答:大 key 和热 key 是 Redis 运维的两个高频隐患,先定义再治理。大 key:value 特别大的键——经验值 String 超过 10KB、集合类元素超过 5000 个就算偏大。危害:单线程模型下对大 key 的操作(特别是删除和序列化)会长时间阻塞主线程,整个实例卡顿;网络传输大 value 挤占带宽;主从同步和持久化都被拖慢。
发现:redis-cli --bigkeys 采样扫描(低峰跑);治理:拆分(大 hash 按字段哈希拆成多个小 key)、异步删除(UNLINK 代替 DEL,4.0+)、压缩 value。热 key:访问频率极端集中的键(秒杀商品、热搜话题)——单 key 打满单个分片或单实例。
发现:--hotkeys(需 LFU 策略)或代理层统计;治理:本地缓存兜一层(应用内存挡住绝大部分读)、key 打散多副本(key:n 随机读一份)、读写分离把读压力分给从库。这两类问题我在云 Redis 场景配合开发定位过方向,属于"原理加协作处理"的口径。
追问链:
- 迭问1:为什么删除大 key 会卡住 Redis? → 答:因为 DEL 是同步操作且在主线程执行:删一个百万元素的 hash,内核要逐个释放元素内存、更新各类元数据,这个过程毫秒到百毫秒级,期间所有其他请求排队——对低延迟服务等于一次故障。解法:4.0 之后用 UNLINK,它把真正的内存释放丢给后台线程异步做,主线程只做摘除标记;老版本的曲线救国是 HSCAN 分批渐删。这个知识点很能体现"对单线程模型的代价有体感"。
关联话术:"'大 key 阻塞、热 key 打偏'这两个词我在配合开发排查缓存抖动时用过——定位手段是 --bigkeys 采样加慢命令日志,治理动作落在应用侧拆 key 和本地缓存。中间件的很多问题最终要应用配合治理,跨团队协作把问题讲清楚,是我做支撑角色的价值。"
3.29 主键、自增与表结构变更的运维注意 【了解】
标准回答:表结构层面运维要操心的几件事,按踩坑频率讲。第一主键必须有:InnoDB 是聚簇索引组织表,没有显式主键会用第一个非空唯一索引顶替、再没有就生成隐藏的 row_id——隐藏列全局共享且不可引用,复制和性能都有隐患,所以建表规范第一条就是显式主键。第二自增列(AUTO_INCREMENT):运维要知道它的行为——MySQL 8.0 之前重启后自增计数可能回退(基于内存最大值),8.0 起持久化了;主从切换后自增 ID 可能冲突是经典问题,所以分库分表要提前规划步长或换分布式 ID(雪花算法)。第三大表 DDL:直接 alter 一张亿级表会锁表数小时——生产用在线 DDL(5.7+ 的 ALGORITHM=INPLACE、8.0 的 INSTANT 秒级加列)或 gh-ost/pt-osc 这类工具做影子表切换;变更前必须评估"这个 DDL 是不是 instant 级、锁不锁、要多久"。第四字符集和排序规则:库表要统一 utf8mb4,混用 utf8 和 utf8mb4 的表 join 时会出现索引失效的隐式转换问题——我在给开发做 SQL 评审时会专门看这个。
追问链:
- 迭问1:pt-online-schema-change / gh-ost 的原理? → 答:影子表思路三步:创建一张结构修改后的新表(空表)→ 在原表上建触发器(或靠 binlog 订阅,gh-ost 的方式不入侵原表),把变更期间的增量 DML 同步到新表,同时分小块把存量数据拷贝过去 → 数据追平后一把 RENAME 换名。全程原表可读写,只在最后 rename 的瞬间有元数据锁。要点:预留磁盘空间(双表并存)、低峰执行、注意外键和长事务的干扰——原理我理解到这个层面,生产上大表 DDL 我还没亲手操作过亿级场景,如实按"懂原理、会评估"口径答。
关联话术:"表结构规范我按'事前评审'的口径聊:主键、字符集、索引这几条我在配合开发评审建表语句时会看;云上数据库审计也能发现'没有主键的表''隐式转换的 SQL'这类问题。运维的价值是把问题拦在上线前——这句话我在数据库话题里常说。"
3.30 本章案例
- 【真实项目】(银行)Vastbase G100 一主一备部署与调优:背景是数币平台需要国产数据库承载合约数据,信创要求 PG 系国产库,且必须适配鲲鹏 ARM 和麒麟 V10。任务是我负责部署一主一备高可用集群并通过客户验收。行动:用海量自动化脚本两节点同时执行安装(误差控制在 10 秒内保证握手),配置 HAS/DCS 开机自启;调优 max_connections 从 100 到 10000、开启线程池 enable_thread_pool;踩掉安装目录权限的坑;license 到期前完成正式 license 替换,并按"先节点 A 重启就绪、再节点 B"的滚动顺序重启 has 避免双主。结果:集群交付通过客户验收,主备角色检查、模拟故障切换、vsql 与 DataStudio 连接测试全部通过,支撑试点业务运行,整套步骤沉淀进公司标准实施文档。这是简历项目一职责原文对应的完整 STAR。
- 【课程项目】MySQL 主从 + 备份恢复演练:搭一主一从环境,验证 show slave status 双 Yes 和 Seconds_Behind_Master 归零;mysqldump 全量加 --flush-logs 切 binlog 做增量;再模拟误删表做恢复演练——测试库导入全备、mysqlbinlog 按位点截取跳过 drop、导出该表回灌。整个流程把 3.4/3.6/3.7 的命令链跑成肌肉记忆,面试口径是"自建实验 + 云上运维结合":实验给我原理和手感,云控制台给我生产规模的操作视角。
- 【经典故障】主从不同步(SQL 线程报错):现象是从库 SQL 线程停了,复制中断。定位:show slave status 的 Last_SQL_Error 指向"记录已存在"类冲突——追溯发现从库被开发直连写入过数据,主库日志重放时撞上冲突。处理:以主库为准删掉从库的冲突行,start slave 恢复;根治动作是把从库设 read_only 加 super_read_only,权限上只保留只读账号,并把"从库绝不直写"写进交付规范。这个案例的教学点在于:技术修复之外必须有制度修复,同样的故障第二次出现就说明第一次没修完。
章末自测清单(快问快答)
- binlog/redo/undo 一句话分工? → binlog 服务层归档与复制;redo 前滚保证持久性;undo 回滚保证原子性(MVCC 也用它)。
- 主从复制三个线程? → 主库 dump、从库 IO 线程(收进 relay log)、从库 SQL 线程(重放)。
- 主从状态看哪三样? → Slave_IO_Running 与 Slave_SQL_Running 双 Yes、Seconds_Behind_Master 延迟。
- SQL 线程停了最常见原因? → 从库被直写导致回放冲突;解法以主库为准修数据+从库设只读。
- mysqldump 备份不锁表的参数? → --single-transaction(InnoDB 快照);--master-data=2 记录 binlog 位点。
- XtraBackup 增量恢复要注意什么? → 增量必须先合并回全备再统一恢复,不能独立恢复。
- 备份策略三层? → 全量(日/周)+ 增量(binlog 留 3-7 天)+ 定期恢复演练。
- explain 里最差的 type? → all(全表扫描);Extra 出现 Using filesort/temporary 要优化。
- 索引失效说三个高频? → 隐式类型转换、like 左模糊、违反联合索引最左前缀(还有函数/运算、!=、not in、or、大结果集)。
- 事务隔离级别 MySQL 默认哪个?哪个级别防幻读? → 默认 RR;SE 全防,InnoDB 在 RR 下靠 MVCC+间隙锁基本防幻读。
- 连接数满第一步做什么? → show full processlist 看会话分布:大量 Sleep 查连接池/wait_timeout,大量慢 Query 走慢查询优化。
- RDB 和 AOF 各自优缺点一句话? → RDB 文件小恢复快但丢窗口数据;AOF 丢得少但文件大恢复慢,4.0+ 混合持久化兼得。
- 哨兵切换流程关键词? → 主观下线 sdown → quorum 客观下线 odown → 选 lead → 挑新主(优先级/偏移量/runid)→ 从库改挂新主。
- 缓存三兄弟一句话画像? → 穿透查不存在的(空值/布隆);击穿热点单过期(互斥锁/逻辑过期);雪崩批量过期或整挂(随机 TTL/高可用/限流)。
- Vastbase 是什么、两个调优参数? → openGauss 内核的 PG 系国产商业库;max_connections 100→10000、enable_thread_pool=on。
- RocketMQ 和 Nacos 各自一句话? → RocketMQ 消息队列(异步/解耦/削峰);Nacos 注册中心+配置中心(服务发现+配置热更新)。