数据库MySQL
1.⭐️⭐️⭐️MySQL的引擎有什么,各种引擎的特点?
常见的有 InnoDB、MyISAM 和 Memory。
- InnoDB 现在是 MySQL 的默认引擎,支持事务,符合 ACID 特性(原子性、一致性、隔离性、持久性),也支持外键约束。它在高并发、需要事务保证一致性的场景里,比如订单或支付系统,基本都是首选。
- MyISAM 是比较早期的引擎,不支持事务和外键,它只有表级锁,但是查询速度会比较快,适合那种读多写少的场景,比如日志或者一些报表类的应用。
- Memory 引擎是把数据直接存在内存里,读写速度非常快,但一旦重启数据就会丢,所以一般用在临时表或者缓存场景。
绝大多数情况下我会选 InnoDB,因为它事务支持好、并发性能也不错,适合互联网业务。
如果是日志类、分析类的读密集场景,可以考虑 MyISAM。
要是临时数据,就会用 Memory,因为速度快,也不怕丢。
| 引擎特性 | InnoDB | MyISAM | Memory |
|---|---|---|---|
| 事务支持 | ✅ 支持(ACID 特性) | ❌ 不支持 | ❌ 不支持 |
| 外键约束 | ✅ 支持 | ❌ 不支持 | ❌ 不支持 |
| 数据存储位置 | 磁盘(数据 + 索引) | 磁盘 | 内存 |
| 查询性能 | 读写均衡(适合并发) | 读性能突出(写操作较慢) | 读写极快(内存速度) |
| 适用场景 | 电商订单、银行转账(需事务和外键) | 日志分析、历史数据查询(读多写少) | 临时统计报表、缓存数据(重启丢失) |
2.⭐️⭐️⭐️详细对比一下InnoDB和MyISAM的区别
它们的区别主要体现在几个方面:
- 事务支持:
InnoDB 支持事务,符合 ACID 特性,可以保证数据的可靠性和一致性;
而 MyISAM 不支持事务,所以更适合一些不需要事务的应用场景。- 数据完整性:
InnoDB 支持外键约束,能保证数据的完整性,比如主表删除时能级联删除子表数据;MyISAM 就不支持外键,完整性需要应用层自己保证。- 锁机制:
InnoDB 用的是 行级锁,并发性能更好;
MyISAM 用的是 表级锁,写的时候会锁整张表,所以在高并发写入下性能会差一些。- 性能特点:
InnoDB 更适合事务密集、并发量大的场景,比如订单、支付这种业务;
MyISAM 在读多写少、只做简单查询时性能更好一些。- 数据恢复:
InnoDB 有崩溃恢复机制,宕机后还能保证数据不丢;
MyISAM 没有这个能力,崩溃后可能会导致表损坏或者数据丢失。大多数互联网业务我都会选 InnoDB,因为它事务支持和并发性能更好,也更安全。
只有在一些特殊场景,比如日志系统、统计分析那种 读多写少 的场景,我才可能考虑 MyISAM。
3.⭐️你知道 CAP 吗?
知道的。CAP 理论主要讲的是在 分布式系统 里,有三个核心特性:
- C,一致性(Consistency):所有节点在同一时间看到的数据是一致的。
- A,可用性(Availability):系统在任何时候都能正常响应请求,不会拒绝服务。
- P,分区容错性(Partition Tolerance):当网络发生分区或者节点通信异常时,系统还能继续提供服务。
CAP 理论的核心结论是:在分布式系统里,这三个特性 最多只能同时满足两个,不可能同时完全满足三个。
像 传统的关系型数据库(比如单机 MySQL),更偏向 CA,因为它保证一致性和可用性,但不具备分区容错性,一旦网络分区就没办法了。
分布式系统一般必须满足 P,所以就只能在 一致性 和 可用性 之间做取舍。
比如 ZooKeeper 更偏向 CP,保证一致性,牺牲了一些可用性。
实际业务中,我会结合业务场景来选。
比如金融、支付系统必须保证一致性,就会偏向 CP;
而像电商的商品详情、推荐服务,更在乎高可用性和用户体验,就会偏向 AP。
节点就是系统里的一台服务器。比如你有一个用户数据库,不是只放在一台机器上,而是放在三台服务器上,这三台服务器就是三个节点。每个节点存着同样或部分数据,它们互相同步,保证整体系统能正常工作。
网络分区不是说整个系统都断了,而是节点之间不能互相通信了。
4.⭐️⭐️Redis vs MySQL?
Redis 和 MySQL 差别挺大,我可以从几个方面来说:
用途方面:
- Redis:内存数据库,主打低延迟、高并发,常用在缓存、计数器、秒杀、点赞这种实时场景;
- MySQL:关系型数据库,更适合做核心业务数据的存储,比如用户信息、订单系统、金融数据这些有结构化关系的场景。
性能方面:
- Redis:Redis 的数据在内存里,读写速度非常快,毫秒级;
- MySQL:MySQL 数据在磁盘上,性能没那么快,但它支持复杂查询和事务,适合需要强一致性的业务。
数据持久化方面:
- Redis:Redis 虽然支持 RDB/AOF 持久化,但核心还是内存存储,出故障可能丢数据;
- MySQL:MySQL 数据都在磁盘里,持久化能力很强,就算服务器挂了也能恢复。
扩展性方面:
- Redis:Redis 扩展比较灵活,可以通过分片水平扩展来支持高并发;
- MySQL:MySQL 也能扩展,但往往要用主从复制、分库分表,大规模场景下复杂度会高一些。
一致性和事务方面:
- Redis:Redis支持简单事务,但不保证严格的 ACID,适合 “最终一致性” 场景。
- MySQL:MySQL 支持完整事务,保证 ACID 特性,所以像转账、订单状态这种必须强一致的业务,一般都会用 MySQL。
Redis 更偏向高速缓存和实时操作,MySQL 更偏向核心业务数据和强一致性,实际系统里通常会把两者结合起来使用。
5.⭐️⭐️⭐️一条SQL语句在MySQL中的执行过程?
这个过程可以分成几个步骤:
- 先建立连接:
客户端发起请求,MySQL 会先做权限验证,确认用户能不能访问数据库。- 然后解析语句:
SQL 发到服务器后,会经过解析器,检查语法对不对,同时把 SQL 拆解成语法树。- 接着优化:
优化器会根据语法树生成执行计划,选择走哪个索引、表连接的顺序怎么排,这一步的目的是找一条“代价最小”的执行路径。- 再执行语句:
执行器拿着执行计划,去调用存储引擎(一般是 InnoDB)的接口,把数据查出来或者写进去。- 最后返回结果:
把查询结果或者操作结果返回给客户端。一条 SQL 大概就是 连接 → 解析 → 优化 → 执行 → 存储引擎 → 返回结果 这样一个流程。
6.⭐️⭐️⭐️⭐️⭐️MySQL中如何定位和优化慢查询?
对于慢查询,一般会分两步走:先定位,再优化。
定位慢查询:
- 第一,可以在 MySQL 配置里开启 慢查询日志,把执行时间超过阈值的 SQL 记录下来
- 第二,针对具体语句,用 EXPLAIN 看执行计划,分析是不是在全表扫描,或者有没有用到索引。
- 如果是线上系统,我还会结合一些 监控工具,比如 Skywalking 这种链路追踪,可以直接看到哪个接口慢,并且细化到 SQL 的执行时间,这样能快速定位问题。
优化慢查询:
- 最常见的是 加合适的索引,比如避免在 where 条件里对索引字段做函数操作。
- 其次是 优化 SQL 写法,减少子查询,避免 select *,尽量只查需要的字段。
- 如果表特别大,可以在 表结构层面优化,比如做分库分表。
- 如果数据库压力实在大,可以在 业务层加缓存,比如 Redis,把热点数据放缓存里,减轻 MySQL 压力。
所以慢查询优化通常是个综合过程,先用日志和 EXPLAIN 把问题 SQL 找出来,再结合索引、SQL 写法、表结构、缓存等手段去优化。



7.⭐️⭐️⭐️⭐️什么是索引?MySQL索引分类?
索引其实就是一种加快数据检索的数据结构,可以理解成书的目录。没有索引的时候,数据库需要全表扫描,一条一条找;有了索引,就能快速定位到目标数据。
在 MySQL 里,常见的索引我一般会从三个角度去分:
按数据结构分
- B+树索引:是最常用的,InnoDB 默认就是用它,适合范围查询。
- 哈希索引:通过哈希函数定位,查询速度非常快,复杂度 O(1),但是只支持等值查询,不支持范围查询,常见于 Memory 引擎。
按作用范围分
- 主键索引:唯一且不能为空。比如用户表的 user_id。
- 唯一索引:保证字段值唯一,但允许有一个空值。比如邮箱避免重复注册。
- 普通索引:最常见的索引,没有唯一性约束。比如在订单表的 create_time 字段建索引,加速按时间查询。
- 联合索引:多个字段组成的索引,注意“最左前缀原则”。
按存储方式分
- 聚簇索引:索引和数据存放在一起,比如 InnoDB 的主键索引,查主键的时候可以直接定位到数据。
- 非聚簇索引:索引和数据分开存,比如普通索引、唯一索引。查的时候要先找到指针,再去表里取数据,这个过程叫“回表”。
索引的本质是用空间换时间,查询更快了,代价是插入和更新会更慢,所以实际使用的时候需要结合业务场景来设计。
8.⭐️⭐️索引的底层数据结构了解过吗?
MySQL 里索引最常见的就是 B+ 树,InnoDB 默认就是用它。
- B+ 树和普通二叉树或 B 树相比,有几个特点:
- 所有数据都在叶子节点,非叶子节点只存索引和指针,用来导航
- 叶子节点之间通过链表连接,所以做范围查询或者顺序扫描的时候特别高效。
- 树高低:每个节点可以有很多子节点,所以同样的数据量下树高比二叉树低很多,查一个值通常只需要 3~4 次磁盘 IO,就能定位到目标数据。
- 除了 B+ 树,还有 哈希索引,它底层是哈希表,查找非常快,复杂度接近 O(1),但是只支持等值查询,不支持范围查询,也不能排序,所以通常只在 Memory 引擎里用。
B+ 树查询范围灵活、效率高、磁盘开销低,特别适合 InnoDB 的索引场景,所以 MySQL 默认选择 B+ 树作为存储结构。
9.⭐️MySQL Hash与 B+树索引的区别?
这两种索引底层结构和使用场景差别挺大的:
- Hash 索引:底层是哈希表,查等值特别快,比如
WHERE column = value。但是不支持范围查询,也不能排序。一般在 Memory 引擎里用,数据在内存里,适合临时表或者缓存场景。- B+ 树索引:底层是 B+ 树,数据存叶子节点,非叶子节点只存索引。既能查等值,也能做范围查询和排序,比如
WHERE column > 10 AND column < 20或ORDER BY。速度比 Hash 稍慢,但功能更全面,InnoDB 默认就是用它,适合大数据量和持久化存储。简单说,Hash 就是快但功能有限,B+ 树功能多,适合大数据量和持久化场景。
10.⭐️⭐️⭐️⭐️⭐️B树,B+树,红黑树的区别是什么呢?
这三种树结构在存储和查询方式上差别挺大的。
1. B 树
- 非叶子节点和叶子节点都存数据。
- 查询时可能在非叶子节点就找到目标,所以查询路径不固定,效率有时候高、有时候低
- 范围查询比较麻烦,需要在不同层级节点之间遍历。
2. B+ 树
- 所有数据都在叶子节点,非叶子节点只存索引。
- 查询必须从根节点到叶子节点,路径固定,所以查询效率稳定。
- 叶子节点之间通过双向链表连接,做范围查询或者顺序扫描很高效。
- 这也是为什么 InnoDB 默认用 B+ 树作为索引的原因。
3. 红黑树
- 属于自平衡二叉查找树,每个节点存数据,且通过红黑规则保持平衡。
- 查询、插入、删除复杂度都是 O(logN),适合内存中快速查找,但不适合存磁盘,也不适合大范围顺序扫描。
简单说就是,B 树和 B+ 树适合磁盘存储,B+ 树范围查询更高效;红黑树适合内存数据,快速查找,但范围查询和磁盘访问效率不如 B+ 树。
- 磁盘访问不友好:B+ 树每个节点可以有很多子节点,树高低、磁盘 I/O 少;而红黑树每个节点只有两个子节点,树高比较高,如果数据在磁盘上,需要频繁读写多个节点,I/O 成本高。
- 范围查询不高效:红黑树没有叶子节点链表,做范围查询必须通过中序遍历整个树,效率比 B+ 树低。
- 所以红黑树适合内存中的快速查找,但不适合大数据量磁盘存储或范围扫描。(数据都在内存里,CPU 可以直接访问,不需要像磁盘那样进行耗时的读写操作。)



11.⭐️⭐️聚簇索引(聚集索引),非聚簇索引(二级索引)?
聚簇索引和非聚簇索引的区别主要在于数据和索引的存放方式。
1. 聚簇索引
- 最关键的特点是数据和索引存放在一起。
- 非叶子节点存索引值,叶子节点存整行数据。
- 一个表只能有一个聚簇索引,通常就是主键。
- 优点是查主键非常快,因为找到索引就直接拿到整行数据,不需要回表。
2. 非聚簇索引
- 数据和索引是分开存的。
- 非叶子节点存索引值,叶子节点存对应主键值。
- 一个表可以有多个非聚簇索引。
- 查询时,需要先查索引找到主键,再回表去查整行数据,这个过程叫回表。
简单说,聚簇索引索引就是数据本身,查起来快但只能有一个;非聚簇索引索引和数据分开,可以有多个,但查询时可能需要回表。
非聚簇索引:索引和数据是分开存储的,有两棵“树”:
索引树:叶子节点存的是索引值 + 对应行的主键(而不是整行数据)。
数据表:数据实际存储在聚簇索引(叶子节点)里。

12. 什么是回表查询?
回表查询其实就是通过索引找不到完整数据,需要再去表里取数据的过程。
举个例子:
在 MySQL 的 InnoDB 里,非聚簇索引(普通索引、唯一索引)叶子节点只存索引字段 + 主键ID,不存整行数据。
当你用这个索引查询时,
先在索引里找到对应的主键ID。
再去聚簇索引(主键索引)里,根据这个主键ID取整行数据。这个再去取整行数据的过程就叫回表。
性能损耗:回表查询需要额外访问数据表,查询效率低。
避免回表:通过 覆盖索引 来避免回表,覆盖索引包含了查询所需的所有列,查询时直接通过索引获取结果,无需访问数据表。
13.什么叫覆盖索引?
- 覆盖索引就是指查询的所有列都在索引里,这样就不用回表去查整行数据,性能会更高
- 使用 id 查询,直接走聚集索引查询,一次索引扫描,直接返回数据,性能高。
- 如果返回的列中没有包含在索引中,可能会触发回表查询。
- 所以我们平时尽量尽量避免使用 select *,利用覆盖索引可以提高查询性能。

14. MySQL超大分页怎么处理?
- 超大分页就是数据量很大时,如果直接用
LIMIT offset, size查询,会非常慢。因为数据库得扫描前面所有的数据行。优化思路:
- 先只查询
id列(通常有索引,查询很快):
select id from tb_sku order by id limit 1000000,10- 确定了id之后,然后再去表中查具体列:
select * from tb_sku t where t.id in ( … 上一步查到的id … )- 这样可以充分利用索引,减少扫描数据量和排序量。
- 因为查询id的时候,走的覆盖索引,所以效率可以提升很多。
select * from tb_sku order by id limit 1000000,10;
MySQL 会先扫描前 1000000 条记录,然后丢掉它们,只保留第 9000001~9000010 条,这个操作非常慢,I/O 非常大。


15. 索引创建原则有哪些?
我觉得索引的原则可以总结成几个方面:
首先,大前提是 数据量大、查询频繁的表才值得建索引,否则没必要。
具体来说:
- 常用在 WHERE、ORDER BY、GROUP BY 里的字段,我会优先建索引,这样能减少全表扫描。
- 联合索引比多个单列索引更高效,因为它可以同时覆盖多个查询条件,还能避免回表,节省存储空间。
- 字段的区分度要高。区分度高指的是字段值分布比较离散,比如
手机号、邮箱。如果字段只有几种取值(比如性别),建索引意义不大。- 联合索引要注意顺序,遵循“最左前缀”原则,把过滤性最强、使用最频繁字段放在前面
- 避免在索引列上做函数或计算。比如
WHERE YEAR(create_time) = 2025会让索引失效。更好的写法是范围查询:WHERE create_time >= '2025-01-01' AND create_time < '2026-01-01'。- 控制索引数量,因为索引虽然提升了查询性能,但会增加增删改的负担,所以要在查询性能和写性能之间做平衡。
16.⭐️⭐️⭐️⭐️⭐️索引失效的场景?
总结了几个主要的场景:
- 第一种,就是在查询条件里对索引列做了运算或者函数操作,会导致索引失效,因为索引存储的是原始值,无法匹配经过计算后的值。
- 第二种,查询条件中使用了LIKE并以通配符%开头时,因为通配符%在开头意味着需要扫描整个表来匹配数据。但如果通配符出现在末尾,索引仍然可以生效。
- 第三种,就是数据类型不匹配。如果索引字段的类型和查询条件的类型不匹配,数据库会进行隐式类型转换,导致索引失效。
- 还有一个常见的,查询中使用了复合索引但未遵循最左前缀原则。比如有 (A,B,C) 这个索引,如果条件里只用了 B 或 C,没有用到 A,那这个索引就没法发挥作用了。
- 另外还有一些情况,比如在 where 条件里用了 OR,如果两边有字段没有索引,整体也可能走不了索引;还有 != 或 not in 这种操作符,也会让数据库选择全表扫描,因为需要扫描大量数据来排除不符合条件的记录。
最后可以选择用
explain去看执行计划,来确认 SQL 有没有走到索引。
17. SQL的优化经验有哪些?
我理解 SQL 优化可以从几个方面入手:
表结构设计
- 在建表的时候就要考虑性能,比如选择合适的数据类型,避免用太大的字段,能用整型就不用字符串,这样存储和比较都会更快。
索引优化
- 索引是提升查询性能的关键,会遵循像区分度高、常出现在查询条件里的字段才建索引,还有联合索引最左前缀原则。
- 同时控制索引数量,避免过多影响写性能。
SQL 语句优化
- 避免写法导致索引失效,比如在索引列上做函数计算。
- 不写
SELECT *,只查需要的列,减少网络传输和回表。UNION能用UNION ALL就用UNION ALL,因为后者不需要去重。- 多表关联时,明确
INNER JOIN、LEFT JOIN的业务含义,合理利用索引字段做连接。架构层面的优化
- 可以用 主从复制、读写分离,让写操作在主库,读操作在从库,避免读写互相影响。
- 如果数据量太大,再考虑 分库分表,把数据分散存储,减少单表的压力。
18.⭐️⭐️⭐️表如何优化?
创建表时,选择字段类型时结合字段内容,比如
- 设置合适的数值类型(TINYINT、INT、BIGINT),要根据实际情况选择
- 设置合适的字符串类型(CHAR、VARCHAR或TEXT)。
char定长效率高,varchar可变长度,效率稍低。
19.⭐️⭐️⭐️索引如何优化?
在使用索引时,我们
- 遵循索引创建原则,
- 确保索引字段是查询频繁的,
- 使用复合索引覆盖SQL返回值,
- 避免在索引字段上进行运算或类型转换,
- 以及控制索引数量。
20.⭐️⭐️⭐️SQL语句优化?
我对SQL语句的优化包括
- SELECT语句指明字段名称而不是使用
SELECT *,- 避免造成索引失效的写法,
- 聚合查询时使用UNION ALL代替UNION,union会多一次过滤,效率低
- 表关联时优先使用INNER JOIN,以及在必须使用LEFT JOIN或RIGHT JOIN时,确保小表作为驱动表。
内连接会对两个表进行优化,优先把小表放到外边,把大表放到里边。left join 或 right join,不会重新调整顺序。
21.⭐️⭐️⭐️事务的四大特性是什么?四大特性的实现在MySQL中怎么保证?
事务有四大特性,也就是 ACID:
- 原子性(Atomicity)
- 事务里的操作要么全部成功,要么全部失败,不会出现只执行一半的情况。
- 在 MySQL 里,原子性主要靠 Undo Log 来保证,事务失败时会用回滚日志把数据恢复到执行前的状态。
- 一致性(Consistency)
- 事务执行前后,数据要保持一致,不会出现违反约束或者逻辑错误的情况。
- MySQL 是通过 约束(外键、唯一性)、触发器、以及原子性+隔离性 一起来保证一致性的。
- 隔离性(Isolation)
- 多个事务并发时,互不干扰。不同隔离级别对应解决不同并发问题,比如脏读、不可重复读、幻读。
- 在 MySQL InnoDB 里,隔离性主要依赖 锁机制 和 MVCC(多版本并发控制) 来实现。
- 持久性(Durability)
- 一旦事务提交,数据就会被持久保存,即使宕机也不会丢失。
- 在 MySQL 里,持久性依靠 Redo Log 和 Binlog,Redo Log 保证崩溃恢复,Binlog 用于主从复制和持久存储。
22. 并发事务带来哪些问题?
- 并发事务可能导致脏读、不可重复读和幻读。
- 脏读:事务A读到了事务B未提交的“脏数据”。如果事务B回滚,事务A读取的数据就变得无效。
- 不可重复读:事务A两次读取同一数据,结果不一致,因为事务B在其中修改并提交了该数据。
- 幻读:事务A按照相同的查询条件多次查询,查询结果的行数发生变化。这是因为在两次查询之间,事务B插入或删除了符合查询条件的数据。

23.⭐️⭐️⭐️⭐️⭐️怎么解决这些问题呢?MySQL的默认隔离级别是?
解决这些问题的方法是使用事务隔离。MySQL支持四种隔离级别:
- 未提交读(READ UNCOMMITTED):
事务可以读取其他事务尚未提交的数据,可能会发生脏读、不可重复读、幻读。
解决不了所有问题。- 读已提交(READ COMMITTED):
事务只能读取其他事务已提交的数据,可能会发生不可重复读、幻读。
能解决脏读,但不能解决不可重复读和幻读。- 可重复读(REPEATABLE READ):
事务在执行期间会锁定查询的数据行,确保该数据在事务完成前不会被其他事务修改。
能解决脏读和不可重复读,但不能解决幻读,这也是MySQL的默认隔离级别。- 串行化(SERIALIZABLE):
事务的执行会是串行执行的,即一个事务执行完成后,另一个事务才能开始。
可以解决所有问题,但性能较低。事务隔离级别越高,数据越安全。
24.⭐️⭐️⭐️MySQL三大日志bin log,undo log和redo log的区别,作用?
Undo Log
- 用于事务回滚,保证 原子性。
比如事务执行出错或回滚,就用 Undo Log 把数据恢复到执行前状态。Redo Log
- 用于崩溃恢复,保证持久性。
事务提交时,先写 Redo Log,再提交,这样即使宕机,也能恢复数据。Binlog(Binary Log):
- 记录 所有写操作的日志,用于 主从复制和增量备份。
- Binlog 可以保证数据同步到从库,也能做审计和恢复操作。
简单记忆:Undo 回滚,Redo 崩溃恢复,Binlog 复制备份。
**25.**⭐️⭐️⭐️事务中的隔离性是如何保证的呢?(解释下MVCC)
- 我理解的事务隔离性,就是保证一个事务在执行过程中,不会被其他事务干扰。
- 数据库保证隔离性一般有两种方式:锁机制和MVCC。
- 先说锁机制,比如行锁或者表锁。当一个事务在操作数据时,其他事务必须等锁释放才能访问,这样可以避免脏读、不可重复读这些问题。但缺点是性能可能受影响,特别是并发量大的时候。
- 所以大多数数据库会用 MVCC,也就是多版本并发控制。它的思路是,不直接覆盖数据,而是给每次修改的数据生成一个新版本,老版本保留给正在执行的事务去读。这样,读和写就不会互相阻塞。
- 比如事务 A 正在读某条记录,事务 B 对它更新数据。B 会生成一个新版本,而 A 看到的还是原来的旧版本。这样既保证了隔离性,又提升了并发性能。数据库会用版本号或时间戳来判断事务该看到哪个版本。
隔离性可以通过锁或者 MVCC 来保证,而 MVCC 的好处是兼顾隔离性和并发性能。
26. MySQL主从同步原理是什么?
好的,我来讲一下。MySQL 的主从同步,本质上就是主库把数据修改记录同步到从库,从而保证数据一致性。整个流程主要分三步:记录 → 传输 → 重放。
- 记录(主库写日志)
主库在执行写操作时,会把这些操作记录到 二进制日志(binlog) 中。这个日志是按照执行顺序记录的,比如插入、更新、删除操作。- 传输(从库拉取日志)
从库会通过一个叫 I/O 线程 的后台线程去读取主库的 binlog,然后存到自己的 中继日志(relay log) 里。- 重放(从库应用日志)
从库还有一个 SQL 线程,它会把中继日志里的操作按顺序执行到自己的数据库里。这样就实现了和主库的数据同步。简单总结就是:主库写操作 → 记录 binlog → 从库拉取 binlog → 写到 relay log → 执行操作

27. 一般是怎么分库的呢?
分库的策略有两种,
- 第一种是垂直分库:按照业务模块将不同的表拆分到不同的库中,比如说用户、登录、权限等表放在用户库中,商品、分类、库存放在商品库中,优惠券、满减、秒杀放在活动库中。
- 第二种是水平分库:按照一定的策略将一个表中的数据拆分到多个库中,比如哈希分片和范围分片,对用户 id 进行取模运算或者范围划分,将数据分散到不同的库中。





28. 那是怎么分表的?
- 当单表超过 500 万条数据,就可以考虑水平分表了。比如说我们可以将文章表拆分成多个表,如 article_0、article_9999、article_19999 等。
- 在码奇交流平台中,我们将文章的基本信息和内容详情做了垂直分表处理,因为文章的内容会占用比较大的空间,在只需要查看文章基本信息时把文章详情也带出来的话,就会占用更多的网络 IO 和内存导致查询变慢;而文章的基本信息,如标题、作者、状态等信息占用的空间较小,很适合不需要查询文章详情的场景。