从上图可以看出, MySQL 主要由下面几部分构成:
连接器: 身份认证和权限相关(登录 MySQL 的时候)。
查询缓存: 执行查询语句的时候,会先查询缓存(MySQL 8.0 版本后移除,因为这个功能不太实用)。
分析器: 没有命中缓存的话,SQL 语句就会经过分析器,分析器说白了就是要先看你的 SQL 语句要干嘛,再检查你的 SQL 语句语法是否正确。
优化器: 按照 MySQL 认为最优的方案去执行。
执行器: 执行语句,然后从存储引擎返回数据。 执行语句之前会先判断是否有权限,如果没有权限的话,就会报错。
插件式存储引擎:主要负责数据的存储和读取,采用的是插件式架构,支持 InnoDB、MyISAM、Memory 等多种存储引擎。
简单来说 MySQL 主要分为 Server 层和存储引擎层:
Server 层:主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图,函数等,还有一个通用的日志模块 binlog 日志模块。
存储引擎:主要负责数据的存储和读取,采用可以替换的插件式架构,支持 InnoDB、MyISAM、Memory 等多个存储引擎,其中 InnoDB 引擎有自有的日志模块 redolog 模块。现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5 版本开始就被当做默认存储引擎了。
连接器主要和身份认证和权限相关的功能相关,就好比一个级别很高的门卫一样。主要负责用户登录数据库,进行用户的身份认证,包括校验账户密码,权限等操作,如果用户账户密码已通过,连接器会到权限表中查询该用户的所有权限,之后在这个连接里的权限逻辑判断都是会依赖此时读取到的权限数据,也就是说,后续只要这个连接不断开,即使管理员修改了该用户的权限,该用户也是不受影响的。
查询缓存主要用来缓存我们所执行的 SELECT 语句以及该语句的结果集。连接建立后,执行查询语句的时候,会先查询缓存,MySQL 会先校验这个 SQL 是否执行过,以 Key-Value 的形式缓存在内存中,Key 是查询预计,Value 是结果集。如果缓存 key 被命中,就会直接返回给客户端,如果没有命中,就会执行后续的操作,完成后也会把结果缓存起来,方便下一次调用。当然在真正执行缓存查询的时候还是会校验用户的权限,是否有该表的查询条件。MySQL 查询不建议使用缓存,因为查询缓存失效在实际业务场景中可能会非常频繁,假如你对一个表更新的话,这个表上的所有的查询缓存都会被清空。对于不经常更新的数据来说,使用缓存还是可以的。所以,一般在大多数情况下我们都是不推荐去使用查询缓存的。MySQL 8.0 版本后删除了缓存的功能,官方也是认为该功能在实际的应用场景比较少,所以干脆直接删掉了。
MySQL 没有命中缓存,那么就会进入分析器,分析器主要是用来分析 SQL 语句是来干嘛的,分析器也会分为几步:第一步,词法分析,一条 SQL 语句有多个字符串组成,首先要提取关键字,比如 select,提出查询的表,提出字段名,提出查询条件等等。做完这些操作后,就会进入第二步。第二步,语法分析,主要就是判断你输入的 SQL 是否正确,是否符合 MySQL 的语法。完成这 2 步之后,MySQL 就准备开始执行了,但是如何执行,怎么执行是最好的结果呢?这个时候就需要优化器上场了。
优化器的作用就是它认为的最优的执行方案去执行(有时候可能也不是最优,这篇文章涉及对这部分知识的深入讲解),比如多个索引的时候该如何选择索引,多表查询的时候如何选择关联顺序等。可以说,经过了优化器之后可以说这个语句具体该如何执行就已经定下来。
当选择了执行方案后,MySQL 就准备开始执行了,首先执行前会校验该用户有没有权限,如果没有权限,就会返回错误信息,如果有权限,就会去调用引擎的接口,返回接口执行的结果。
MyISAM 和 InnoDB 是 MySQL 数据库中两种不同的存储引擎。
MyISAM 只有表级锁(table-level locking),而 InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁。使用MyISAM时,当一个连接正在修改一个表时,其他连接无法同时对该表进行修改。而 InnoDB 使用行级锁定,这意味着多个连接可以同时修改同一个表中的不同行。
MyISAM 不提供事务支持。InnoDB 提供事务支持,实现了 SQL 标准定义了四个隔离级别,具有提交(commit)和回滚(rollback)事务的能力。并且,InnoDB 默认使用的 REPEATABLE-READ(可重读)隔离级别是可以解决幻读问题发生的(基于 MVCC 和 Next-Key Lock)。
这意味着在 MyISAM 中,如果有多个并发连接进行写操作,则可能会出现数据损坏或丢失的情况。而 InnoDB 可以通过使用锁定和回滚机制来保证数据的一致性和完整性。
MyISAM 不支持,而 InnoDB 支持。
外键对于维护数据一致性非常有帮助,但是对性能有一定的损耗。因此,通常情况下,我们是不建议在实际生产项目中使用外键的,在业务代码中进行约束即可!
MyISAM 不支持,而 InnoDB 支持。使用 InnoDB 的数据库在异常崩溃后,数据库重新启动的时候会保证数据库恢复到崩溃前的状态。这个恢复的过程依赖于 redo log 。
MyISAM 不支持,而 InnoDB 支持。
虽然 MyISAM 引擎和 InnoDB 引擎都是使用 B+Tree 作为索引结构,但是两者的实现方式不太一样。InnoDB 引擎中,其数据文件本身就是索引文件。而MyISAM,索引文件和数据文件是分离的,其表数据文件本身就是按 B+Tree 组织的一个索引结构,树的叶节点 data 域保存了完整的数据记录。
InnoDB 的性能比 MyISAM 更强大,不管是在读写混合模式下还是只读模式下,随着 CPU 核数的增加,InnoDB 的读写能力呈线性增长。MyISAM 因为读写不能并发,它的处理能力跟核数没关系。
InnoDB 支持行级别的锁粒度,MyISAM 不支持,只支持表级别的锁粒度。
MyISAM 不提供事务支持。InnoDB 提供事务支持,实现了 SQL 标准定义了四个隔离级别。
MyISAM 不支持外键,而 InnoDB 支持。
MyISAM 不支持 MVCC,而 InnoDB 支持。
虽然 MyISAM 引擎和 InnoDB 引擎都是使用 B+Tree 作为索引结构,但是两者的实现方式不太一样。
MyISAM 不支持数据库异常崩溃后的安全恢复,而 InnoDB 支持。
InnoDB 的性能比 MyISAM 更强大。
InnoDB 存储引擎支持行级锁和表级锁的两种锁模式。通常情况下,事务在获取行级锁之前必须先获取表的表级锁。这样可以保证行级锁和表级锁之间的一致性。
意向锁(Intention Lock)是 InnoDB 存储引擎中一种辅助锁机制,主要用来协调行级锁和表级锁之间的关系。它可以用来表示一个事务想要对表中的某些行加锁或释放锁。
意向锁有两种:IS(Intention Shared)和IX(Intention Exclusive)。IS 表示事务想要在表的某行或行集合上获取共享锁。IX 表示事务想要在表的某行或行集合上获取排他锁。意向锁只控制了行级锁和表级锁之间的关系,不会影响其他事务的行级锁操作。
意向锁的主要作用有:
协调行级锁和表级锁:将意向锁添加到表中,表示其他事务正在使用行级锁。如果某个事务需要对该表获取表锁或行级锁,则需要在获取表级锁或行级锁之前,先获取相应类型的意向锁,从而保证行级锁和表级锁之间的一致性。
提高性能:由于意向锁的加锁范围比行锁更广,所以使用意向锁可以减少锁资源的争用和冲突,提高系统的并发能力和性能。
防止死锁:在 InnoDB 中一个事务要加行级锁或意向锁时,必须先获取相应的表级意向锁。这样可以避免出现死锁。
总之,意向锁是 InnoDB 存储引擎中重要的辅助锁机制,通过协调行级锁和表级锁之间的关系来提高系统的并发性能和可靠性,防止出现死锁的情况。
这主要是由于以下几个原因:
减轻主服务器的负担:如果直接将二进制日志写入从库,那么主服务器需要同时处理大量的读取请求和写入请求,会导致主服务器负载过高。通过先将二进制日志写入中继日志,可以让主服务器只需处理写入请求,减轻其负担。
提高复制性能:通过使用中继日志,从库可以异步地读取中继日志并将其应用到本地数据库中,而无需等待主服务器的响应。这样可以提高复制的速度和性能。
提高数据可靠性:如果直接将二进制日志写入从库,从库可能会在写入过程中出现故障或者网络连接中断,导致部分数据丢失。通过使用中继日志,可以将二进制日志在主服务器上备份,从而避免数据丢失的风险。
综上所述,使用中继日志可以提高复制性能、减轻主服务器的负担,并提高数据可靠性,是 MySQL 复制过程中必要的一步。