MySQL原理解析

逻辑架构mysql

MySQL逻辑架构总体分为三层:sql

  1. 客户端层,链接处理、受权认证、安全等功能均在这一层处理。 
  2. 核心服务层,包括查询解析、分析、优化、缓存、内置函数(好比:时间、数学、加密等函数)。全部的跨存储引擎的功能也在这一层实现:存储过程、触发器、视图等。
  3.  存储引擎,其负责MySQL中的数据存储和提取。和Linux下的文件系统相似,每种存储引擎都有其优点和劣势。中间的服务层经过API与存储引擎通讯,这些API接口屏蔽了不一样存储引擎间的差别

存储引擎数据库

主要介绍InnoDB引擎和MyISAM引擎缓存

InnoDB引擎:安全

  1. 将数据存储在表空间中,表空间由一系列的数据文件组成,由InnoDB管理;
  2. 支持每一个表的数据和索引存放在单独文件中(innodb_file_per_table);
  3. 支持事务,采用MVCC来控制并发,并实现标准的4个事务隔离级别,支持外键;
  4. 索引基于聚簇索引创建,对于主键查询有较高性能;
  5. 数据文件的平台无关性,支持数据在不一样的架构平台移植;
  6. 可以经过一些工具支持真正的热备。如XtraBackup等;
  7. 内部进行自身优化如采起可预测性预读,可以自动在内存中建立hash索引等。

MyISAM引擎:服务器

  1.    不支持事务和行级锁;
  2.    提供大量特性如全文索引、空间函数、压缩、延迟更新等;
  3.    数据库故障后,安全恢复性差;
  4.    对于只读数据能够忍受故障恢复,MyISAM依然很是适用;
  5.   日志服务器的场景也比较适用,只需插入和数据读取操做;
  6.    不支持单表一个文件,会将全部的数据和索引内容分别存在两个文件中;
  7.    MyISAM对整张表加锁而不是对行,因此不适用写操做比较多的场景;
  8.    支持索引缓存不支持数据缓存。

查询过程数据结构

咱们但愿经过MySQL能够得到更好的查询性能,最好的方式就是弄清楚MySQL是如何执行查询的,理解了这一点,咱们能够依据它的规则去优化SQL语句。架构

当向MySQL发送一个SQL请求的时候,究竟发生了什么呢,以下:并发

客户端/服务端通讯协议数据库设计

一、MySQL客户端/服务端通讯协议是半双工的:在任一时刻,要么是服务器向客户端发送数据,要么是客户端向服务器发送数据,这两个动做不能同时发生。一旦一端开始发送消息,另外一端要接收完整个消息才能响应它,因此咱们没法将一个消息切成小块独立发送,也没有办法进行流量控制。 

 

二、客户端用一个单独的数据包将查询请求发送给服务器,因此当查询语句很长的时候,须要设置max_allowed_packet参数。可是须要注意的是,若是查询实在是太大,服务端会拒绝接收更多数据并抛出异常。

 

三、服务器响应给用户的数据一般会不少,由多个数据包组成。可是当服务器响应客户端请求时,客户端必须完整的接收整个返回结果,而不能只取部分结果,而后让服务器中止发送。于是在实际开发中,尽可能保持查询简单且只返回必需的数据,减少通讯间数据包的大小和数量是一个很是好的习惯,这也是查询中尽可能避免使用SELECT *以及加上LIMIT限制的缘由之一。

 

小结:请求语句有大小限制,不该过长;减少通讯间数据包大小及通讯数量

 

查询缓存

在解析一个查询语句前,若是查询缓存是打开的,那么MySQL会检查这个查询语句是否命中查询缓存中的数据。若是当前查询刚好命中查询缓存,在检查一次用户权限后直接返回缓存中的结果。这种状况下,查询不会被解析,也不会生成执行计划,更不会执行。

 

MySQL将缓存存放在一个引用表(相似于HashMap的数据结构),经过一个哈希值索引,这个哈希值经过查询语句、查询的数据库、客户端协议版本号等一些可能影响结果的信息计算得来。因此两个查询在任何字符上的不一样(例如:空格、注释),都会致使缓存不会命中。

 

若是查询中包含任何用户自定义函数、存储函数、用户变量、临时表、mysql库中的系统表,其查询结果都不会被缓存。好比函数NOW()或者CURRENT_DATE()会由于不一样的查询时间,返回不一样的查询结果,再好比包含CURRENT_USER或者CONNECION_ID()的查询语句会由于不一样的用户而返回不一样的结果,将这样的查询结果缓存起来没有任何的意义。

 

MySQL的查询缓存系统会跟踪查询中涉及的每一个表,若是这些表(数据或结构)发生变化,那么和这张表相关的全部缓存数据都将失效。正由于如此,在任何的写操做时,MySQL必须将对应表的全部缓存都设置为失效。若是查询缓存很是大或者碎片不少,这个操做就可能带来很大的系统消耗,甚至致使系统僵死一下子。

查询缓存对系统的额外消耗不只仅在写操做,读操做也不例外:

  • 任何的查询语句在开始以前都必须通过检查,即便这条SQL语句永远不会命中缓存
  • 若是查询结果能够被缓存,那么执行完成后,会将结果存入缓存,也会带来额外的系统消耗基于此,咱们要知道并非什么状况下查询缓存都会提升系统性能,缓存和失效都会带来额外消耗,只有当缓存带来的资源节约大于其自己消耗的资源时,才会给系统带来性能提高。但要如何评估打开缓存是否可以带来性能提高是一件很是困难的事情,也不在本文讨论的范畴内。若是系统确实存在一些性能问题,能够尝试打开查询缓存,并在数据库设计上作一些优化,好比:
  • 用多个小表代替一个大表,注意不要过分设计
  • 批量插入代替循环单条插入
  • 合理控制缓存空间大小,通常来讲其大小设置为几十兆比较合适
  • 能够经过SQL_CACHE和SQL_NO_CACHE来控制某个查询语句是否须要进行缓存

 

不要轻易打开查询缓存,特别是写密集型应用。若是必定要开启查询缓存,能够将query_cache_type设置为DEMAND,只有查询语句加入SQL_CACHE的查询才会走缓存,其余查询则不会,这样能够很是自由地控制哪些查询须要被缓存。

 

语法解析和预处理

MySQL经过关键字将SQL语句进行解析,而且建立内部数据结构解析树,这个过程解析器主要经过语法规则来验证和解析,好比是否使用了错误的关键字,查询的数据表和列是否存在等,而后对其进行各类优化,包括重写查询,决定表的读写顺序,以及选择合适的索引等。用户能够经过特殊的关键字提示(hint)优化器,影响它的决策过程。也能够请求优化器解释(explain)优化过程的各个因素,使用户知道服务器如何进行优化决策的,这个比较实用,尤为是优化某个查询语句时。

相关文章
相关标签/搜索