MySQL的逻辑架构自顶向下大致可分为四层,包括网络连接层、服务层、引擎层和存储层。
客户端连接器(Client Connectors):提供与MySQL服务器建立的支持。目前几乎支持所有主流 的服务端编程技术,例如常见的 Java、C、Python、.NET等,它们通过各自API技术与MySQL建立连接。
用户鉴权:当客户端向MySQL服务端发起连接请求后,MySQL server会对发起连接的用户进行鉴权处理,MySQL鉴权依据是: 用户名,客户端主机地址和用户密码
安全管理:当客户连接到MySQL server后,MySQL server会根据用户的权限来判断用户具体可执行哪些操作
MySQL 提供的部分权限
show privileges \G
服务层是MySQL Server的核心,主要包含系统管理和控制工具、连接池、SQL接口、解析器、查询优化器和缓存六个部分
连接池(Connection Pool):负责存储和管理客户端与数据库的连接,一个线程负责管理一个连接。[官网性能测试报告:引入线程池,性能稳定性与性能会有很大得提升,128并发,读写模式, mysql高出60倍,只读18倍,若不引用线程池,线程创建关闭性能消耗大]
系统管理和控制工具(Management Services & Utilities):例如备份恢复、安全管理、集群管理等
SQL接口(SQL Interface):用于接受客户端发送的各种SQL命令,并且返回用户需要查询的结果。比如DML、DDL、存储过程、视图、触发器等。
解析器(Parser):负责将请求的SQL解析生成一个"解析树"。然后根据一些MySQL规则进一步检查解析树是否合法。
查询优化器(Optimizer):当“解析树”通过解析器语法检查后,将交由优化器将其转化成执行计划,然后与存储引擎交互。
缓存(Cache&Buffer): 缓存机制是由一系列小缓存组成的。比如表缓存,记录缓存,权限缓 存,引擎缓存等。如果查询缓存有命中的查询结果,查询语句就可以直接去查询缓存中取数据。
存储引擎负责MySQL中数据的存储与提取,与底层系统文件进行交互。MySQL存储引擎是插件式的,服务器中的查询执行引擎通过接口与存储引擎进行通信,接口屏蔽了不同存储引擎之间的差异 。
现在有很多种存储引擎,各有各的特点,最常见的是MyISAM和InnoDB。
负责将数据库的数据和日志存储在文件系统之上,并完成与存储引擎的交互,是文件的物理存储层。主要包含日志文件,数据文件,配置文件,pid 文件,socket 文件等。
当前使用比较多的是MyISAM和Innodb 存储引擎,在MySQL8.0后不在支持MyISAM,默认都是用Innodb。
Innodb 体系结构是由多个内存块组成的缓冲池及多个后台进程组成。主要包括内存,线程和磁盘文件。
以Page页为单位,默认大小16K。底层采用链表结构管理Page。在InnoDB访问表记录和索引时会在Page页中缓存,以减少磁盘IO操作,提升效率。
free list :表示空闲缓冲区,管理free page
flush list:表示需要刷新到磁盘的缓冲区,管理dirty page,内部page按修改时间排序。
lru list:表示正在使用的缓冲区,管理clean page和dirty page
末尾淘汰法,新数据从链表头部加入,释放空间时从末尾淘汰
链表分为new和old两个部分,加入元素时并不是从表头插入,而是从中间midpoint位置插入,如果数据很快被访问,那么page就会向new列表头部移动,如果数据没有被访问,会逐步向old尾部移动,等待淘汰。
每当有新的page数据读取到buffer pool时,InnoDb引擎会判断是否有空闲页,是否足够,如果有就将free page从free list列表删除,放入到LRU列表中。没有空闲页,就会根据LRU算法淘汰LRU链表默认的页,将内存空间释放分配给新的页
show variables like '%innodb_page_size%'; --查看page页大小 show variables like '%innodb_old%'; --查看lru list中old列表参数 show variables like '%innodb_buffer%'; --查看buffer pool参数
建议:将innodb_buffer_pool_size设置为总内存大小的60%-80%,
innodb_buffer_pool_instances可以设置为多个,这样可以避免缓存争夺。
在进行DML操作时,如果Buffer Pool(BP)没有其相应的Page数据,并不会立刻将磁盘页加载到缓冲池,而是在Change Buffer记录缓冲变更,等未来数据被读取时,再将数据合并恢复到BP中。
Change Buffer占用Buffer Pool空间,默认占25%,最大允许占50%,可以根据读写业务量来进行调整。
show variables like 'innodb_change_buffer_max_size';
当更新一条记录时,该记录在Buffer Pool存在,直接在Buffer Pool修改,一次内存操作。如果该记录在Buffer Pool不存在(没有命中),会直接在Change Buffer进行一次内存操作,不用再去磁盘查询数据,避免一次磁盘IO。当下次查询记录时,会先进行磁盘读取,然后再从Change Buffer中读取信息合并,最终载入Buffer Pool中。
用来保存要写入磁盘上log文件(Redo/Undo
)的数据,日志缓冲区的内容定期刷新到磁盘log文件中。日志缓冲区满时会自动将其刷新到磁盘,当遇到 BLOB
或多行更新的大事务操作时,增加日志缓冲区可以节省磁盘I/O。
Log Buffer
主要是用于记录 InnoDB
引擎日志,在 DML
操作时会产生Redo
和Undo
日志。
Log Buffer
空间满了,会自动写入磁盘。可以通过将 innodb_log_buffer_size
参数调大,减少磁盘IO频率。innodb_flush_log_at_trx_commit
参数控制日志刷新行为,默认为1。
InnoDB 存储结构主要有Tablespaces,InnoDB Data Dictionary,Doublewrite Buffer、Redo Log 和 Undo Logs。
表空间用于存储表结构和数据。
系统表空间存储 InnoDB 数据字典,Doublewrite Buffer,Change Buffer,Undo Logs。任何用户创建的表数据和索引数据不指定独立表空间时,也会存储在系统表空间中。系统表空间是一个共享的表空间,它被多个表共享。
系统表空间的数据文件通过参数innodb_data_file_path
控制,默认值是ibdata1:12M:autoextend(文件名为ibdata1、12MB、自动扩展)
show variables like 'innodb_data_file_path';
独立表空间是一个单表表空间,单独为该表创建自己的数据文件,而不是在系统表空间中。当innodb_file_per_table
选项开启时,表将被创建于表空间中。否则,innodb将被创建于系统表空间中。每个表文件表空间由一个.ibd数据文件表示,该文件默认被创建于数据库目录中。表空间的表文件支持动态(dynamic)和压缩(commpressed)行格式。
show variables like 'innodb_file_per_table';
通过create tablespace语法创建的共享表空间,可以创建在mysql数据目录外其它表空间
CREATE TABLESPACE ts1 ADD DATAFILE ''/data1/ts1.ibd' Engine=InnoDB; CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1;
临时表空间分为:session temporary tablespace 和 global temporary tablespace
由一个或多个包含Undo日志文件组成,在MySQL 5.6版本之前Undo放在系统表空间共享区。从5.6新增参数innodb_undo_directory、innodb_undo_logs和innodb_undo_tablespaces这3个参数,可以把undo log从ibdata1移出来单独存放。需要在初始化时配置独立的Undo表空间
MySQL 5.7引入了新的参数,innodb_undo_log_truncate,开启后可在线收缩拆分出来的undo表空间。
undo表空间文件可在线收缩的条件:
undo表空间的自动truncate相关参数:
CREATE TABLESPACE tablespace_name InnoDB and NDB: ADD DATAFILE 'file_name' InnoDB only: [FILE_BLOCK_SIZE = value] NDB only: USE LOGFILE GROUP logfile_group [EXTENT_SIZE [=] extent_size] [INITIAL_SIZE [=] initial_size] [AUTOEXTEND_SIZE [=] autoextend_size] [MAX_SIZE [=] max_size] [NODEGROUP [=] nodegroup_id] [WAIT] [COMMENT [=] 'string'] InnoDB and NDB: [ENGINE [=] engine_name]
select * from information_schema.INNODB_SYS_TABLESPACES ;
段是表空间的主要组织结构,用来管理物理文件。创建一个索引(B+树)时,默认同时创建两个段,分别是内节点段(存储主键)和叶子节点段(存储数据)
区是由物理上连续分配的一段空间(每个区的大小都为1MB),默认innodb页(16K)的情况下,一个区由64个连续页组成。【16K * 64 = 1M】
页是文件管理的最小单位,默认每个页的大小为16KB。innodb_page_size参数可以配置页面大小(2KB,4KB, 8KB,16KB等)
常见的页类型:
关系型数据库中数据是按行进行存放的。
redo log 记录的是数据库中每个页的修改,而不是某一行或某几行修改成怎样,可以用来恢复提交后的物理数据页,且只能恢复到最后一次提交的位置。
undo log的作用是提供事务的回滚和多个行版本控制(MVCC-非锁定读)。undo log是逻辑日志,如执行一条delete操作时,undo log将它的反向操作记录下来,undo log也会产生redo日志。当事务失败需要回滚时,就可以从undo log中的逻辑记录进行回滚到修改前的样子。