文章目录
MySQL自问自答
Drip
2025-06-03 21:20
累计阅读11
评论0

MySQL中,如何定位慢查询?

嗯,我们当时在做压力测试时发现有些接口响应时间非常慢,超过了2秒。

因为我们的系统部署了运维监控系统Skywalking,在它的报表展示中可以看到哪个接口慢,并且能分析出接口中哪部分耗时较多,包括具体的SQL执行时间,这样就能定位到出现问题的SQL。

如果没有这种监控系统,MySQL本身也提供了慢查询日志功能。可以在MySQL的系统配置文件中开启慢查询日志,并设置SQL执行时间超过多少就记录到日志文件,比如我们之前项目设置的是2秒,超过这个时间的SQL就会记录在日志文件中,我们就可以在那里找到执行慢的SQL。

我记得当时,我们的一个接口处理了大量的订单查询请求。通过慢查询日志,我们发现有个SQL是要求全表扫描的,而且当时条件查询字段没有加索引,导致响应时间比较慢,之后我记得我们给userID加上了索引,响应时间最后从2秒减少到了300毫秒。

那这个SQL语句执行很慢,如何分析呢?

如果一条SQL执行很慢,我们通常会使用MySQL的EXPLAIN命令来分析这条SQL的执行情况。

通过keykey_len可以检查是否命中了索引,如果已经添加了索引,也可以判断索引是否有效。

通过type字段可以查看SQL是否有优化空间,比如是否存在全索引扫描或全表扫描。通过extra建议可以判断是否出现回表情况,如果出现,可以尝试添加索引或修改返回字段来优化。

image-20250428175421801

了解过索引吗?(什么是索引)

索引是一种特殊的数据结构,用于加快数据库中数据查询的速度,降低数据库的I/O成本。它类似于书中的目录,可以帮助快速查找特定的数据。(有序)

同时,索引列可以对数据进行排序,降低数据排序的成本,也能减少CPU的消耗。(不需要全表扫描)

我们通常所说的索引,包括聚集索引、覆盖索引、组合索引、前缀索引、唯一索引等,没有特别说明,默认都是使用B+树结构组织的索引。

索引的底层数据结构了解过吗?

MySQL的默认存储引擎InnoDB使用的是B+树作为索引的存储结构。选择B+树(多叉路平衡查找树)的原因包括:

节点可以有更多子节点,路径更短;

磁盘读写代价更低,非叶子节点只存储键和指针(即索引字段和指针),叶子节点存储数据;

B+树适合范围查询和扫描,因为叶子节点形成了一个双向链表。

B树和B+树的区别是什么呢?

B树和B+树的主要区别在于:

  1. B树的非叶子节点和叶子节点都存放数据,而B+树的所有数据只出现在叶子节点,这使得B+树在查询时效率更稳定。

  2. B+树在进行范围查询时效率更高,因为所有数据都在叶子节点,并且叶子节点之间形成了双向链表。

image-20250429165104573

什么是聚簇索引什么是非聚簇索引(二级索引)?

聚簇索引是指数据与索引放在一起,B+树的叶子节点保存了整行数据,通常只有一个聚簇索引,一般是由主键构成。

非聚簇索引则是数据与索引分开存储,B+树的叶子节点保存的是主键值,可以有多个非聚簇索引,通常我们自定义的索引都是非聚簇索引。

image-20250429165617949

知道什么是回表查询吗

要先介绍聚集索引和二级索引

回表查询是指通过二级索引找到对应的主键值,然后再通过主键值查询聚簇索引中对应的整行数据的过程。

image-20250429165728739

知道什么叫覆盖索引吗?

覆盖索引指的是查询使用了索引,返回的列,必须能在索引中全部能够找到

使用ID查询,直接走聚集索引,一次索引扫描,直接返回数据,避免回表查询。

如果返回的列没有索引,那么就可能触发回表查询,所以我们在项目开发中会很少使用select *

image-20250429170131282

MySQL超大分页怎么处理?

超大分页通常发生在数据量大的情况下,使用LIMIT分页查询且需要排序时效率较低。可以通过覆盖索引和子查询来解决。首先查询数据的ID字段进行分页,然后根据ID列表用子查询来过滤只查询这些ID的数据,因为查询ID时使用的是覆盖索引,所以效率可以提升。

image-20250429173245705

索引创建原则有哪些?(索引的优化)

创建索引的原则包括:

  • 数据量大,并且查询比较频繁的(比如数据量超过10万以上时考虑创建索引) 重要

  • 选择查询频繁的字段作为索引,如查询条件、排序字段或分组字段。重要

  • 尽量使用联合索引,覆盖SQL的返回值。重要

  • 对于内容较长的字段,考虑使用前缀索引。重要

  • 控制索引数量,因为索引虽然可以提高查询速度,但也会影响插入、更新的速度。重要

image-20250429173308266

什么情况下索引会失效?(索引的优化)

索引可能在以下情况下失效:

  • 没有遵循最左匹配原则。

  • 使用了模糊查询且%号在前面。

  • 在索引字段上进行了运算或类型转换。

  • 使用了复合索引但在中间使用了范围查询,导致右边的条件索引失效。所以范围的字段在建联合索引时就要放在最右边

image-20250429191114058

SQL的优化经验有哪些?

SQL优化可以从以下几个方面考虑:

  • 建表时选择合适的字段类型。

  • 使用索引,遵循创建索引的原则。

  • 编写高效的SQL语句,比如避免使用SELECT *,尽量使用UNION ALL代替UNION,以及在表关联时使用INNER JOIN

  • 采用主从复制和读写分离提高性能。

  • 在数据量大时考虑分库分表。

创建表的时候,你们是如何优化的呢?

创建表时,我们主要参考阿里开发手册,选择字段类型时结合字段内容,比如数值类型选择TINYINTINTBIGINT等,字符串类型选择CHARVARCHARTEXT

image-20250429195100906

事务的特性是什么,可以详细说一下吗?

事务是一组操作的集合,他是一个不可分割的工作单位。事务会把这些所有操作视为一个整体,要么全部成功,要么全部失败。

他的特性就是:ACID。分别指的是原子性,一致性,隔离性,持久性。

我举个例子吧,A像B转账1000元。 转账成功,A扣除1000,B增加1000。原子操作体现在要么都成功,要么都失败。

在转账的过程中,数据要一致。A扣除了1000,B增加了1000.

在转账的过程中,隔离性体现在A向B转账,不收其他事务干扰

持久化体现在,事务提交后,要把数据持久化,数据落盘。

并发事务会带来哪些问题?

嗯。并发事务可能导致脏读,不可重复读,幻读

首先是脏读,脏读指的是一个事务读到了另一个事务未提交的数据。也就是说,当一个事务正在访问数据并对数据进行了修改,此时这种修改还并未提交到数据库中,另一个事务也访问了这个数据,因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据就是”脏数据“。

第二是不可重复读,是指在一个事务内多次读取同一事务。在这个事务还没有结束时,另一个事务也访问该数据,那么在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样,这就发生了在一个事务内两次读到的数据是不一样的情况,因此被称为不可重复读。

第三是幻读,幻读与不可重复读类似,它发生在一个事务读取了几行数据,接着另一个并发事务插入了一些数据。在随后的查询中,第一个事务就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,因此被称为幻读。

image-20250503182137515

事务隔离级别有哪些?MySQL的默认隔离级别是什么

MySQL有四种隔离级别,分别有:读未提交,读已提交,可重复读,串行化。

  1. 读未提交是最低的隔离级别,一个事务可以读取另一个事务为提交的数据,容易出现脏读,不可重复读,幻读等问题

  2. 读已提交指的是一个事务只能读取另一个事务已经提交的数据,可以避免脏读

  3. 可重复读是MySQL的默认隔离级别,指一个事务开始后,不允许其他事务修改该事务使用的数据,可以避免脏读和不可重复读

  4. 串行化是最高的隔离级别,完全的隔离事务,每个事务都必须等待前一个事务提交后才能执行,避免了所有并发问题。性能比较低。

undo log 和redo log的区别

好的。其中redo log日志记录的是数据页的物理变化,当服务器宕机后,可以用redo log来进行数据同步。比如:当服务器重启时,redo log可以"重做"已经提交但还没来得及写入数据文件的事务,来保持数据的一致性。

而undo log主要记录的是逻辑日志,当事务发生回滚时,可以通过逆操作来恢复原来的数据,比如当我们删除一条数据时,undo log就会在日志文件里插入一条与之响应的insert语句,如果回滚就执行该操作。这么做来保持事务的原子性和一致性。另外。在 MVCC 中,事务可以通过 Undo Log 访问旧版本的数据,构建读视图ReadView。

事务当中的隔离性是如何保证的呢?(解释一下MVCC)

事务的隔离性主要由排它锁和MVCC来实现的。

其中MVCC的意思是:多版本并发控制为每个事务提供数据的“快照”版本,让读操作不会被写操作阻塞,读写不互相阻塞,从而提升数据库的并发性能。MVCC通过快照主要解决了脏读和不可重复读的问题。

他的底层实现主要是分为了3个部分:隐藏字段,undo log日志,readView读视图

隐藏字段是指:在mysql中给每个表都设置了隐藏字段,有一个是trx_id(事务ID),记录每一次操作的事务ID,是自增的。另一个是roll_pointer(回滚指针),指向上一个事务版本记录地址。

undo log主要作用是记录回滚日志,存储老版本数据。在内部会形成一个版本链,在多个事务并行操作某一行记录时,记录不同事务修改数据的版本,通过roll_pointer指针形成一个链表。

readView读视图解决的是,在一个事务查询选择版本时,在内部定义了匹配规则和当前事务的ID,判断应该访问哪个版本的数据。不同的隔离级别快照读是不一样的,最终的访问结果也不一样。如果是RC(读已提交)隔离级别下,每一次执行快照读都会生成ReadView,而子啊RR(可重复读)下,只在事务第一次执行快照读时生成ReadView,后续复用。

image-20250516181816813

MYSQL的主从同步的原理是什么?

mysql的主从同步的核心就是binlog二进制文件,他记录了所有的数据定义语言DDL和数据操作语言DML。

具体的流程大致是这样的:

  1. Master主库在事务提交时,会把数据变更记录到binlog中

  2. 从库读取主库的binlog,写入到从库的中继日志RelayLog里。

  3. 从库会重做中继日志的事件,达到与主库同步的效果。

你们项目用过MySQL的分库分表吗?

我们采用微服务架构,每个微服务对应一个数据库,是根据业务进行拆分的,这个其实就是垂直拆分。

那你之前使用过水平分库吗

使用过。当时业务发展迅速,某个表数据量超过1000万,单库优化后性能仍然很慢,因此采用了水平分库。我们首先部署了3台服务器和3个数据库,使用mycat进行数据分片。旧数据也按照ID取模规则迁移到了各个数据库中,这样各个数据库可以分摊存储和读取压力,解决了性能问题。

为什么分布式系统中无法同时保证一致性和可用性?

在分布式系统中,为了保证分区容错性,我们通常需要在一致性和可用性之间做出选择。如果系统优先保证一致性,可能需要牺牲可用性,反之亦然。

什么是BASE理论?

BASE理论是分布式系统设计中对CAP理论中AP方案的延伸,强调通过基本可用、软状态和最终一致性来实现系统设计。

你们采用哪种分布式事务解决方案?

我们项目中使用了Seata的AT模式来解决分布式事务问题。AT模式通过记录业务数据的变更日志来保证事务的最终一致性。

评论