1. MySQL 索引的最左前缀匹配原则是什么?
定义: 在使用联合索引时,查询条件必须从索引的最左侧开始匹配, 以此往右匹配
底层原理: 联合索引在 B+ 树中的排列方式遵循“从左到右”的顺序, 例如联合索引 (a, b, c) 会按照 (a, b, c) 的顺序在 B+ 树中进行排序。
2. 数据库的脏读、不可重复读和幻读分别是什么?
-
定义
- 脏读(Dirty Read): 一个事务读取到另一个事务未提交的数据。如果该未提交事务最终被回滚,那么第一个事务读取的数据就是不一致的(脏的)。
- 不可重复读(Non-repeatable Read): 在同一事务中,
读取同一数据两次
,但由于其他事务的提交,读取的结果不同。例如,事务 A 读取了一行数据,事务 B 修改并提交了这行数据,导致事务 A 再次读取时得到不同的值。 - 幻读(Phantom Read): 在同一事务中,执行相同的查询操作,
返回的结果集
由于其他事务的插入而发生变化。例如,事务 A 查询符合某条件的记录,事务 B 插入了新记录并提交,导致事务 A 再次查询时看到不同的记录数量
-
几种读与隔离级别的关系(脏读、不可重复读和幻读是不同隔离级别下可能发生的问题):
- 读未提交允许脏读。 读已提交防止脏读,但可能出现不可重复读。
- 可重复读防止脏读和不可重复读,但仍可能出现幻读。
- 串行化防止所有三种问题,但性能开销较大。
-
注意不可重复读与幻读的区别
- 幻读是指在事务期间,对于数据总量的突然增加或减少,将别的事务提交的读取到了(针对于数据的数量)
- 不可重复读是指对于同一条数据,在事务执行期间,里面的字段内容发生了变化,读取到了别的事务提交修改的数据。(针对于数据的内容)。
3. MySQL 的存储引擎InnoDB和MYISAM之间有什么区别?
-
InnoDB:
- 支持事务, 提供中四种隔离级别, 默认可重复读
- 支持外键
- 适合高并发的OLTP的场景
- 主键索引与数据存储在一起, 非主键索引仅存储索引值和主键
-
MYISAM
- 不支持事务
- 不支持外键
- 适合读多写少的OLAP的场景
- 索引与主键分开存储的
4. MySQL 的覆盖索引是什么?
MySQL 的覆盖索引(Covering Index)是指二级索引中包含了查询所需的所有字段,从而使查询可以仅通过访问二级索引而不需要访问实际的表数据(主键索引)。
5. MySQL 的索引类型有哪些?
- 数据结构
- B+树索引
- 哈希索引
- 倒排索引(Full-Text)
- R-树索引(多维空间树)
- 索引性质
- 普通索引(二级索引、辅助索引)
- 主键索引
- 联合索引
- 唯一索引
- 全文索引
- 空间索引
- InnoDB B+ 树索引角度来看
- 聚簇索引(只能有一个主键索引)(Clustered Index)
- 非聚簇索引(二级索引)(Non-clustered Index)
6. MySQL InnoDB 引擎中的聚簇索引和非聚簇索引有什么区别?
- 聚簇索引
- 索引叶子结点存储的是数据行,可以直接访问完整数据。
- 每个表只能有一个聚簇索引,通常是主键索引,适合范围查询和排序。
- 非聚簇索引
- 索引叶子节点存储的是数据行的主键和对应的索引列,需通过主键才能访问完整的数据行。
- 一个表可以有多个非聚簇索引(称之为非主键索引、辅助索引、二级索引),适用于快速查找特定列的数据。
7. MySQL 的索引下推是什么?
索引下推(Index Condition Pushdown, ICP)是一种减少回表查询,提高查询效率的技术。
它允许 MySQL 在使用索引查找数据时,将部分查询条件下推到存储引擎层过滤,从而减少需要从表中读取的数据行,减少了 IO(本该由 Server 层做操作,交由存储引擎层因此叫做 “下推” ) 。
==注意==:索引下推是应用在联合索引上的。
8. MySQL 中的回表是什么?
"回表"是指在使用二级索引(非聚簇索引)作为条件进行查询时,由于二级索引中只存储了索引字段的值和对应的主键值,无法得到其它数据。
如果要查询数据行中的其它数据,需要根据主键去聚簇索引查找实际的数据行,这个过程被称为回表。
9. MySQL 中使用索引一定有效吗?如何排查索引效果?
-
索引不一定失效
- 查询条件不匹配:当查询条件中不包含索引列,或者查询条件复杂且不遵循索引的顺序时,索引可能无法被利用。
- 低基数列(区分度小的列):对于基数较低(即不同值较少)的列创建索引效果不佳,因为这样的索引区分度不高。
- 小表全表扫描更优:对于较小的表,MySQL 可能会选择全表扫描而非使用索引,因为在这种情况下,全表扫描的成本可能更低。
-
如何排查索引效果?
使用 EXPLAIN 命令:通过在查询前加上 EXPLAIN,可以查看 MySQL 选择的执行计划,评估是否使用了索引、使用了哪个索引以及估算的行数等信息。
- type(访问类型):显示查询使用的访问方法。理想情况下应为 index 或 range,表示使用了索引;若为 ALL,则意味着进行了全表扫描。
- key(使用的索引):显示实际使用的索引名称。如果此值为 NULL,则表示未使用任何索引。
- rows(扫描的行数):显示查询扫描的行数,用于评估查询效率和潜在性能瓶颈。
10. MySQL 中的索引数量是否越多越好?为什么?
- 时间
- 写入开销增加:每次对表进行 INSERT、UPDATE 或 DELETE 操作时,所有相关的索引都需要同步更新,导致写入操作的时间开销增大。特别是对于频繁更新的字段,维护多个索引会显著影响性能。
- B+ 树维护复杂性:索引更新过程中可能涉及 B+ 树的页分裂或合并操作,进一步增加了时间成本。
- 查询优化器负担:过多的索引会使 MySQL 查询优化器在选择最优执行计划时耗费更多时间,甚至可能导致误选次优索引,影响查询效率。
- 空间
额外存储需求:每个二级索引都会创建一个新的 B+ 树结构,默认每个数据页大小为 16KB。当数据量庞大且索引众多时,会占用大量磁盘空间。
11. MySQL 中如何进行 SQL 调优?
-
合理设计索引,避免回表的发生,减少一次查询和随机 I/O
-
利用联合索引进行覆盖索引的优化,联合索引需满足最左匹配原则
-
避免在 SQL 中进行函数计算等操作,使得无法命中索引
-
避免使用 %LIKE,导致全表扫描
-
避免 SELECT * ,只查询必要的字段
-
不要对无索引字段进行排序操作
-
连表查询需要注意不同字段的字符集是否一致,否则也会导致全表扫描
-
连表时使用小表操控大表的方式
除此之外,还可以利用缓存来优化,一些变化少或者访问频繁的数据设置到缓存中,减轻数据库的压力,提升查询的效率。
还可以通过业务来优化,例如少展示一些不必要的字段,减少多表查询的情况,将列表查询替换成分页分批查询等等。
12. 如何使用 MySQL 的 EXPLAIN 语句进行查询分析?
- id:查询的执行顺序的标识符,值越大优先级越高。简单查询的 id 通常为 1,复杂查询(如包含子查询或 UNION)的 id 会有多个。
- select_type(重要):查询的类型,如 SIMPLE(简单查询)、PRIMARY(主查询)、SUBQUERY(子查询)等。
- table:查询的数据表。
- type(重要):访问类型,如 ALL(全表扫描)、index(索引扫描)、range(范围扫描)等。一般来说,性能从好到差的顺序是:const > eq_ref > ref > range > index > ALL。
- system:表示查询的表只有一行(系统表)。这是一个特殊的情况,不常见。
- const:表示查询的表最多只有一行匹配结果。这通常发生在查询条件是主键或唯一索引,并且是常量比较。
- eq_ref:表示对于每个来自前一张表的行,MySQL 仅访问一次这个表。这通常发生在连接查询中使用主键或唯一索引的情况下。
- ref:MySQL 使用非唯一索引扫描来查找行。查询条件使用的索引是非唯一的(如普通索引)。
- range:表示 MySQL 会扫描表的一部分,而不是全部行。范围扫描通常出现在使用索引的范围查询中(如 BETWEEN、>, <, >=, <=)。
- index:表示 MySQL 扫描索引中的所有行,而不是表中的所有行。即使索引列的值覆盖查询,也需要扫描整个索引。
- all(性能最差):表示 MySQL 需要扫描表中的所有行,即全表扫描。通常出现在没有索引的查询条件中。
- possible_keys:可能用到的索引。
- key(重要):实际用到的索引。
- key_len:用到索引的长度。
- ref:显示索引的哪一列被使用。
- rows(重要):估计要扫描的行数,值越小越好。 filtered:显示查询条件过滤掉的行的百分比。一个高百分比表示查询条件的选择性好。
- Extra(重要):额外信息,如 Using index(表示使用覆盖索引)、Using where(表示使用 WHERE 条件进行过滤)、Using temporary(表示使用临时表)、Using filesort(表示需要额外的排序步骤)。
13. 在什么情况下,不推荐为数据库建立索引?
- 对于数据量很小的表: 当表的数据量很小(如几百条记录)时,建立索引并不会显著提高查询性能,反而可能增加管理的复杂性。
- 频繁更新的表: 对于频繁进行插入、更新和删除操作的表,索引会导致额外的维护开销,因为每次数据变更时都需要更新索引,这会影响性能。
- **执行大量的 SELECT ***: 此时二级索引可能不会显著提升性能,因为需要大量的回表查询,开销大,数据库最终可能会选择走全表扫描。
- 低选择性字段(高度重复值的列):
- 当索引字段的取值重复度高(如性别字段“男”、“女”),索引的效果不明显,且会增加存储空间的浪费。
- 还有一种场景可以考虑,比如表里任务 status 列就 2 个类型,90 % 都是 1(已完成),10%(待执行) 是 2,这个场景会频繁查询 2(待执行)的任务来执行,此时可以建立索引,毕竟能过滤 90 % 的数据。
- 低频查询的列: 对于查询频率极低的字段,建立索引的成本和维护负担可能超过带来的性能提升
- 长文本字段(非常长的 varchar 或 JSON、BLOB 和 TEXT 类型,这些类型的列通常包含大量数据)
- 数据量大排序时都无法用内存排,只能利用磁盘文件,排序很慢。
- 数据量大,每个页能存放的行数就少,扫描查询可能会涉及大量的 I/O。
- 文本字段过大都需要额外 blob 页存储,每次查询还需要查额外的页,也是随机 I/O 效率低。
- 这种类型的数据如果有查询需求,不应该放到 MySQL 中,可以需要采用 es 等组件来实现查询。
14. 在 MySQL 中建索引时需要注意哪些事项?
- 不能盲目的建立索引,索引并不是越多越好,索引会占用空间,且每次修改的时可能都需要维护索引的数据,消耗资源。
- 对于字段的值有大量重复的不要建立索引。比如说:性别字段,在这种重复比例很大的数据行中,建立索引也不能提高检索速度。但是也不绝对,例如定时任务的场景,大部分任务都是成功,少部分任务状态是失败的,这时候通过失败状态去查询任务,实际上能过滤大部分成功的任务,效率还是可以的。
- 对于一些长字段不应该建立索引。比如 text、longtext 这种类型字段不应该建立索引。因为占据的内存大,扫描的时候大量加载至内存中还耗时,使得提升的性能可能不明显,甚至可能还会降低整体的性能,因为别的缓存数据可能因为它被踢出内存,下次查询还需要从磁盘中获取。
- 当数据表的修改频率远大于查询频率时,应该好好考虑是否需要建立索引。因为建立索引会减慢修改的效率,如果很少的查询较多的修改,则得不偿失。
- 对于需要频繁作为条件查询的字段应该建立索引。在 where 关键词后经常查询的字段,建立索引能提高查询的效率,如果有多个条件经常一起查询,则可以考虑联合索引,减少索引数量。
- 对经常在 order by、group by、distinct 后面的字段建立索引。这些操作通常需要对结果进行排序、分组或者去重,而索引可以帮助加快这些操作的速度。
15. 请详细描述 MySQL 的 B+ 树中查询数据的全过程
- 数据从根节点找起,根据比较数据键值与节点中存储的索引键值,确定数据落在哪个区间,从而确定分支,从上到下最终定位到叶子节点
- 叶子节点存储实际的数据行记录,但是一页有 16kb 大小,存储的数据行不止一条
- 叶子节点中数据行以组的形式划分,利用页目录结构,通过二分查找可以定位到对应的组
- 定位组后,利用链表遍历就可以找到对应的数据行
16. 为什么 MySQL 选择使用 B+ 树作为索引结构?
- 高效的查找性能
B+ 树是一种自平衡树,每个叶子节点到根节点的路径长度相同,B+ 树在插入和删除节点时会进行分裂和合并操作,以保持树的平衡,但它又会有一定的冗余节点,使得删除的时候树结构的变化小,更高效。
查找、插入、删除等操作的时间复杂度为 O(log n),能够保证在大数据量情况下也能有较快的响应时间。 - 树的高度增长不会过快,使得查询磁盘的 I/O 次数减少
B+ 树不像红黑树,数据越多树的高度增长就越快。它是多叉树,非叶子节点仅保存主键或索引值和页面指针,使得每一页能容纳更多的记录,因此内存中就能存放更多索引,容易命中缓存,使得查询磁盘的 I/O 次数减少。 - 范围查询能力强
B+ 树特别适合范围查询。因为叶子节点通过链表链接,从根节点定位到叶子节点查找到范围的起点之后,只需要顺序扫描链表即可遍历后续的数据,非常高效。
17. 详细描述一条 SQL 语句在 MySQL 中的执行过程。
先通过连接器校验权限;利用分析器进行 SQL 语句的词法分析和语法分析;构建解析树, 使用优化器选择合适的索引和表连接顺序,最终选择一个最佳的执行计划;利用执行器,调用引擎层查询数据,返回结果集给客户端。
- 当客户端的 SQL 发送到 MySQL 时,首先是到达 Server 层的连接器,连接器会对你此次发起的连接进行权限校验,以此来获取你这个账号拥有的权限。当你的账号或密码不正确时,会报 Access denied for user 错误,相信大家对这个错误也并不陌生。连接成功如果后续没有任何操作,那么这个连接就处于空闲状态,到达一定时间后它便会断开连接,这个时间一般是 8 小时,是由 wait_timeout 参数控制的。
- 查询缓存(在 MySQL 8.0 之后就被砍了)具体做法就是将一个查询语句作为 key ,将上一次请求的结果作为 value,存储在缓存组件中,当同样的语句来查询的时候即可立马返回结果,不需要经历词法、语法分析等以下的步骤。只要表有数据改动缓存就失效了,在我们常见的联机事务处理(OLTP) 场景下是个鸡肋。
- 接下来就到了分析器来进行语法分析、词法分析。MySQL 会首先对你的语句进行 ”词法分析“ ,来判断你的语句是什么类型以及携带什么参数等。比如:MySQL 会将输入语句的 select 提取出来,判断出这是一条查询语句、将 from 后面的 user 提取出来作为查询的表名、把 id 提取出来作为列名等。做完这些 MySQL 将会进行 ”语法分析“ 来判断你的语句的语法是否有误、是否满足 MySQL 的语法。如果语法有问题,那这个错误相信大家都不陌生:You have an error in your SQL syntax; check the manual......。
- 经过分析器就到了优化器,它会对你的语句进行优化判断。比如你的表中有多个索引,优化器会帮你选择使用哪个索引、你使用了 join 多表连接,优化器会帮你调整表的连接顺序。我们平日里用的 explain 其实就是让 MySQL 告诉我们它的优化决定策略是怎样的。
- 最后会到达执行器,它先会判断你对这个 user 表是否有权限查询,如果没有权限它将会拒绝本次查询,返回错误信息。如果有权限,它将会根据表的存储引擎提供的接口进行数据查询将重复遍历表的行数据,判断 id 字段是否等于 1。直到遍历完整个表将符合条件的数据作为结果集返回给客户端。
18. MySQL 是如何实现事务的?
- MySQL 利用锁(行锁、间隙锁等等)机制,使用数据并发修改的控制,满足事务的隔离性。
- Redo Log(重做日志),它会记录事务对数据库的所有修改,当 MySQL 发生宕机或崩溃时,通过重放 redolog 就可以恢复数据,用来满足事务的持久性。
- Undo Log(回滚日志),它会记录事务的反向操作,简单地说就是保存数据的历史版本,用于事务的回滚,使得事务执行失败之后可以恢复之前的样子。实现原子性和隔离性
- MVCC(多版本并发控制),满足了非锁定读的需求,提高了并发度,实现了读已提交和可重复读两种隔离级别,实现了事务的隔离性。
19. MySQL 中的 MVCC 是什么?
- MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种并发控制机制,允许多个事务同时读取和写入数据库,而无需互相等待,从而提高数据库的并发性能。
- 在 MVCC 中,数据库为每个事务创建一个数据快照。每当数据被修改时,MySQL 不会立即覆盖原有数据,而是生成新版本的记录。每个记录都保留了对应的版本号或时间戳。
- 多版本之间串联起来就形成了一条版本链,这样不同时刻启动的事务可以无锁地获得不同版本的数据(普通读)。此时读(普通读)写操作不会阻塞。
- 写操作可以继续写,无非就是会创建新的数据版本(但只有在事务提交后,新版本才会对其他事务可见。未提交的事务修改不会影响其他事务的读取),历史版本记录可供已经启动的事务读取。
20. MySQL 事务的二阶段提交是什么?
MySQL 事务的二阶段提交是指在 MySQL 中,为了确保redo log(重做日志)和 binlog(二进制日志)之间的一致性,使用的一种机制。MySQL 通过二阶段提交来保证在crash recovery(崩溃恢复)时,不会出现数据丢失或数据不一致的情况。
- 准备阶段(Prepare Phase):在事务提交时,MySQL 的 InnoDB 引擎会先写入 redo log,并将其状态标记为prepare,表示事务已经准备提交但还未真正完成。此时的 redo log 是预提交状态,还未标记为完成提交。
- 提交阶段(Commit Phase):当 redo log 的状态变为 prepare 后,MySQL Server 会写入 binlog(记录用户的 DML 操作)。binlog 写入成功后,MySQL 会通知 InnoDB,将 redo log 状态改为commit,完成整个事务的提交过程。
21. MySQL 中的事务隔离级别有哪些?
- 读未提交(READ UNCOMMITTED): 这是最低的隔离级别,在该级别下,一个事务可以看到另一个事务尚未提交的数据修改。这可能会导致脏读问题,即读取到其他事务未提交的数据。
- 读已提交(READ COMMITTED): 在这个级别下,一个事务只能看到已经提交的其他事务所做的修改。这可以避免脏读问题,但是可能会引发不可重复读问题,即在同一个事务中,相同的查询可能返回不同的结果。
- 可重复读(REPEATABLE READ): 在这个级别下,确保在一个事务中的多个查询返回的结果是一致的。这可以避免不可重复读问题,但是可能会引发幻读问题,即在同一个事务中,多次查询可能返回不同数量的行(MySQL 默认的隔离级别)。
- 串行化(SERIALIZABLE)
- 并发 SQL 事务在 SERIALIZABLE 隔离级别下的执行被保证是可串行化的。可串行化执行被定义为:并发执行的 SQL 事务的操作,其效果与这些 SQL 事务按某种顺序串行执行的效果相同。串行执行是指每个 SQL 事务在下一个 SQL 事务开始之前完成其全部操作 来源 SQL92定义。
- 这是最高的隔离级别,在这个级别下,保证事务间的操作结果相当于一个按顺序执行的单线程操作。这可以避免所有的并发问题,但是会大大降低并发性能。
22. MySQL 中有哪些锁类型?
- 行级锁(Row Lock)(重点)
仅对特定的行加锁,允许其他事务并发访问不同的行,适用于高并发场景。 - 表级锁(Table Lock)(重点)
对整个表加锁,其他事务无法对该表进行任何读写操作,适用于需要保证完整性的小型表。 - 意向锁(Intention Lock)
一种表锁,用于表示某个事务对某行数据加锁的意图,分为意向共享锁(IS)和意向排它锁(IX),主要用于行级锁与表级锁的结合。 - 共享锁(Shared Lock)(重点)
允许多个事务并发读取同一资源,但不允许修改。只有在释放共享锁后,其他事务才能获得排它锁。 - 排它锁(Exclusive Lock)(重点)
允许一个事务对资源进行读写,其他事务在获得排它锁之前无法访问该资源。 - 元数据锁(Metadata Lock, MDL)
用于保护数据库对象(如表和索引)的元数据,防止在进行 DDL 操作时其他事务对这些对象进行修改。 - 间隙锁(Gap Lock)(重点)
针对索引中两个记录之间的间隙加锁,防止其他事务在这个间隙中插入新记录,以避免幻读。间隙锁不锁定具体行,而是锁定行与行之间的空间。 - 临键锁(Next-Key Lock)(重点)
是行级锁和间隙锁的结合,锁定具体行和其前面的间隙,确保在一个范围内不会出现幻读。常用于支持可重复读的隔离级别。 - 插入意向锁(Insert Intention Lock)
一种等待间隙的锁,用于指示事务打算在某个间隙中插入记录,允许其他事务进行共享锁,但在插入时会阻止其他的排它锁。 - 自增锁(Auto Increment Lock)
在插入自增列时,加锁以保证自增值的唯一性,防止并发插入导致的冲突。通常在插入操作时被使用,以确保生成的自增 ID 是唯一的。
23. MySQL 中如果发生死锁应该如何解决?
- 自动检测与回滚
- MySQL 自带死锁检测机制(innodb_deadlock_detect),当检测到死锁时,数据库会自动回滚其中一个事务,以解除死锁。通常会回滚事务中持有最少资源的那个。
- 有锁等待超时的参数(innodb_lock_wait_timeout),当获取锁的等待时间超过阈值时,就释放锁进行回滚。
- 手动 kill 发生死锁的语句
- 可以通过命令,手动快速地找出被阻塞的事务及其线程 ID,然后手动 kill 它,及时释放资源。
-
- 使用一下语句查看当前锁和锁等待情况, 通过 INFORMATION_SCHEMA 的 innodb_trx 可以找到事务ID和线程 ID 的对应关系。
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
- 使用一下语句查看当前锁和锁等待情况, 通过 INFORMATION_SCHEMA 的 innodb_trx 可以找到事务ID和线程 ID 的对应关系。
-
- 手动终止该事务:KILL [thread_id];
常见避免死锁或降低死锁的手段
- 避免大事务。大事务占据锁的时间长,将大事务拆分成多个小事务快速释放锁,可降低死锁产生的概率和避免冲突。
- 调整申请锁的顺序。在更新数据的时候要保证获得足够的锁,举个例子:先获取影响范围大的锁,比如说修改操作,先将排他锁获取到,再获取共享锁。或固定顺序访问数据,这样也能避免死锁的情况。
- 更改数据库隔离级别。可重复读比读已提交多了间隙锁和临键锁,利用读已提交替换之可降低死锁的情况。
- 合理建立索引,减少加锁范围。如果命中索引,则会锁对应的行,不然就是全表行都加锁,这样冲突大,死锁的概率就高了。
5)开启死锁检测,适当调整锁等待时长。
24. MySQL 中如何解决深度分页的问题?
- 子查询
通过上次最小字段, 查询指定后n条数据, 再进行join连接 - 记录 id
每次分页都返回当前的最大 id ,然后下次查询的时候,带上这个 id,就可以利用 id > maxid 过滤了。 这种查询仅适合连续查询的情况,如果跳页的话就不生效了。 - elasticsearch
- Scroll API: 只使用滚动查询, 不适合分页查询
- Search After: 需要根据上次结果进行查询
25. 什么是 MySQL 的主从同步机制?它是如何实现的?
- MySQL 的主从同步机制是一种数据复制技术,用于将主数据库(Master)上的数据同步到一个或多个从数据库(Slave)中。
- 主要是通过二进制日志(Binary Log,简称 binlog)实现数据的复制。主数据库在执行写操作时,会将这些操作记录到 binlog 中,然后推送给从数据库,从数据库重放对应的日志即可完成复制。
26. 如何处理 MySQL 的主从同步延迟?
首先需要明确一个点延迟是必然存在的,无论怎么优化都无法避免延迟的存在,只能减少延迟的时间。
- 二次查询
如果从库查不到数据,则再去主库查一遍,由 API 封装这个逻辑即可,算是一个兜底策略,比较简单。不过等于读的压力又转移到主库身上了,如果有不法分子故意查询必定查不到的查询,这就对主库产生冲击了。 - 使用缓存
主库写入后同步到缓存中,这样查询时可以先查询缓存,避免了延迟的问题,不过又引入了缓存数据一致性的问题。 - 关键业务读写都走主库
非关键还是读写分离。比如上面我举例的用户注册这种,可以读写主库,这样就不会有登陆报该用户不存在的问题,这种访问量频次应该也不会很多,所以看业务适当调整此类接口。
27. 如何在 MySQL 中监控和优化慢 SQL?
- 可以利用 MySQL 自带的 slow_query_log 来监控慢 SQL,它是 MySQL 提供的一个日志功能,用于记录执行时间超过特定阈值的 SQL 语句。
- 对于慢查询,再使用 EXPLAIN 分析执行计划,查看查询的执行顺序、使用的索引、扫描的行数等,以识别潜在的性能瓶颈。
评论区