1 MySQL的整体架构是怎样的?
MySQL主要分为四层架构,分别是网络连接层、服务层、存储引擎层、物理层。
● 网络连接层:主要负责连接管理。MySQL服务器上维护了一个线程池(即数据库连接池),每个客户端对应服务器上的一个线程。
● 服务层:MySQL的核心层,包括查询缓存、解析器、预处理器、查询优化器。
查询缓存:在进行查询之前,服务器会先检查查询缓存,如果能找到对应的查询,则直接返回缓存中的结果集。
解析器:根据查询语句构造出一个解析树。主要用于语法分析。
预处理器:进行语义分析。
查询优化器:将解析树转化为执行计划。一般情况下,一条查询可以有多种执行方式,最终返回相同的结果,优化器就是找到其中最优的执行计划。
● 存储引擎层:负责数据的存储和提取。通过提供一系列接口来屏蔽不同引擎之间的差异。
● 物理层:数据文件。
1.1 MySQL常用的存储引擎有哪些?
MySQL中最常用的存储引擎有InnoDB和MyISAM。
1.1.1 InnoDB和MyISAM有什么区别?
区别有:
InnoDB支持事务,MyISAM不支持事务。
InnoDB支持外键,MyISAM不支持外键。
InnoDB索引是聚集索引,MyISAM索引是非聚集索引。
InnoDB支持表级锁、行级锁(默认),MyISAM只支持表级锁。
InnoDB表必须有唯一索引,MyISAM可以没有。
1.1.2 InnoDB引擎的索引数据结构是怎样的?
B+树,其特点是:
非叶子结点不存储数据,只存储索引。
叶子结点之间用指针连接,形成链表。
1.1.3 为什么不用B树?
MySQL从磁盘中读取数据的方式是按页读取,一个磁盘页的默认大小是16KB。
如果使用B树作为索引结构,每个结点中既存储索引又存储数据,能存的索引数较少,B树就可能会很高,而且B树没有维护叶子结点之间的指针,不能进行范围查找。
1.2 说说你知道的索引吧。
单值索引、复合索引、全文索引;B+树索引、Hash索引;聚集索引、非聚集索引。
● 单值索引:一个索引只包含一个列,一个表中可以有多个单值索引。
普通索引:基本索引类型,没有什么限制,允许重复和为空,纯粹是为了查询数据更快一些。
唯一索引:不允许重复,但可以为空。
主键索引:不允许重复和为空。
复合索引:表中多个字段组合形成的索引,使用时遵循最左前缀原则。
全文索引:只有在MyISAM引擎上才能使用。原理是先定义一个词库,然后在文章中查找每个词条(term)出现的频率和位置,把这样的频率和位置信息按照词库的顺序归纳,这样就相当于对文件建立了一个以词库为目录的索引,这样查找某个词的时候就能很快的定位到该词出现的位置。
● B+树索引:MySQL在大多数场景下使用的索引。
Hash索引:数组+链表,对索引的key进行一次hash计算就可以定位出数据存储的位置,适用于等值查询,且比B+树索引更高效,但不能进行范围查询。
● 聚集索引:索引和数据放在同一个文件中(如InnoDB)。
非聚集索引:索引和数据分开放在不同的文件中(如MyISAM)。
1.2.1 什么情况下索引会失效?
在下列情况下,索引会失效:
WHERE条件里有不等于号。
WHERE条件里使用了函数。
模糊查询的第一个字符是通配符。
某个数据列里包含许多重复的值。
2 你知道数据库事务的隔离级别吗?
SQL标准定义了四种隔离级别,MySQL全部都支持。这四种隔离级别分别是:
● 读未提交(READ UNCOMMITTED):不加锁,任何事务对数据的修改都会第一时间暴露给其它事务。可能会发生脏读、不可重复读、幻读。
● 读已提交(READ COMMITTED):一个事务只能读到其它事务已经提交过的数据。不会发生脏读,可能会发生不可重复读、幻读。
● 可重复读(REPEATABLE READ):事务不会读到其它事务对已有数据的修改,即使其它事务已提交,也就是说,事务开始时读到的已有数据是什么,在事务提交前的任意时刻,这些数据的值都是一样的。不会发生脏读、不可重复读,可能会发生幻读。(MySQL的可重复读级别解决了幻读问题)
● 串行化(SERIALIZABLE):将事务的执行变为顺序执行,后一个事务执行必须等待前一个事务结束。不会发生脏读、不可重复读、幻读。
2.1 什么是脏读、不可重复读、幻读?
● 脏读:读未提交隔离等级下,A事务(未提交)修改一条数据后,B事务能直接读取到修改后的数据,若A事务发生回滚,B事务就读到了脏数据。
● 不可重复读:读已提交和读未提交隔离等级下,B事务读取一条数据后,A事务(已提交)修改了这条数据,B事务再次读这条数据时,读到了修改后的数据——B事务两次读取数据的结果不一致。
● 幻读:可重复读、读已提交、读未提交隔离等级下,A事务(已提交)插入了一条新数据,B事务在A事务提交前后读到表中的数据总数不一样。
3 MySQL是怎么保证事务原子性和持久性的?
原子性:利用了undo log。undo log在事务修改数据时产生,当MySQL需要进行事务回滚时,可以通过undo log撤销所有已经成功执行的SQL语句。
持久性:利用了redo log。在事务提交的时候,必须先将该事务的所有事务日志写入磁盘上的redo log中。