zoukankan      html  css  js  c++  java
  • MySQL-体系结构

    一.MySQL体系架构

     

    1、Mysql是由SQL接口,解析器,优化器,缓存,存储引擎组成的(SQL Interface、Parser、Optimizer、Caches&Buffers、Pluggable Storage Engines)

    第一层:客户端

      并不是MySQL独有的技术,它们都是服务于C/S程序或者是这些程序所需要的 :连接处理,身份验证,安全性等等

    (1) Connectors指的是不同语言中与SQL的交互 (并不是MySQL独有的技术,它们都是服务于C/S程序或者是这些程序所需要的 :连接处理,身份验证,安全性等等)

    第二层:SQL Layer。MySQL的核心部分

      这是MySQL的核心部分。通常叫做 SQL Layer。在 MySQL据库系统处理底层数据之前的所有工作都是在这一层完成的,包括权限判断, sql解析,行计划优化, query cache 的处理以及所有内置的函数(如日期,时间,数学运算,加密)等等。各个存储引擎提供的功能都集中在这一层,如存储过程,触发器,视 图等。

    (2)Management Serveices & Utilities: 系统管理和控制工具,例如备份恢复、Mysql复制、集群等 
    (3)Connection Pool: 连接池:管理缓冲用户连接、用户名、密码、权限校验、线程处理等需要缓存的需求 
    (4)SQL Interface: SQL接口:接受用户的SQL命令,并且返回用户需要查询的结果。比如select from就是调用SQL Interface 
    (5)Parser: 解析器,SQL命令传递到解析器的时候会被解析器验证和解析。解析器是由Lex和YACC实现的,是一个很长的脚本, 主要功能: 
    a . 将SQL语句分解成数据结构,并将这个结构传递到后续步骤,以后SQL语句的传递和处理就是基于这个结构的 
    b. 如果在分解构成中遇到错误,那么就说明这个sql语句是不合理的 
    (6)Optimizer: 查询优化器,SQL语句在查询之前会使用查询优化器对查询进行优化。他使用的是“选取-投影-联接”策略进行查询。 
    用一个例子就可以理解: select uid,name from user where gender = 1; 
    这个select 查询先根据where 语句进行选取,而不是先将表全部查询出来以后再进行gender过滤 
    这个select查询先根据uid和name进行属性投影,而不是将属性全部取出以后再进行过滤 
    将这两个查询条件联接起来生成最终查询结果

    (7) Cache和Buffer(高速缓存区): 查询缓存,如果查询缓存有命中的查询结果,查询语句就可以直接去查询缓存中取数据。 
    通过LRU算法将数据的冷端溢出,未来得及时刷新到磁盘的数据页,叫脏页。 
    这个缓存机制是由一系列小缓存组成的。比如表缓存,记录缓存,key缓存,权限缓存等 

    第三层:存储引擎层

      通常叫做StorEngine Layer ,也就是底层数据存取操作实现部分,由多种存储引擎共同组成。它们负责存储和获取所有存储在MySQL中的数据。就像Linux众多的文件系统 一样。每个存储引擎都有自己的优点和缺陷。服务器是通过存储引擎API来与它们交互的。这个接口隐藏 了各个存储引擎不同的地方。对于查询层尽可能的透明。这个API包含了很多底层的操作。如开始一个事 物,或者取出有特定主键的行。存储引擎不能解析SQL,互相之间也不能通信。仅仅是简单的响应服务器 的请求

    (8)Engine :存储引擎。存储引擎是MySql中具体的与文件打交道的子系统。也是Mysql最具有特色的一个地方。 
    Mysql的存储引擎是插件式的。它根据MySql AB公司提供的文件访问层的一个抽象接口来定制一种文件访问机制(这种访问机制就叫存储引擎) 
    现在有很多种存储引擎,各个存储引擎的优势各不一样,最常用的MyISAM,InnoDB,BDB 
    默认下MySql是使用MyISAM引擎,它查询速度快,有较好的索引优化和数据压缩技术。但是它不支持事务。 
    InnoDB支持事务,并且提供行级的锁定,应用也相当广泛。 
    Mysql也支持自己定制存储引擎,甚至一个库中不同的表使用不同的存储引擎,这些都是允许的 

    一条SQL的执行过程

     MySQL是单进程,多线程

    连接管理和安全

    在服务器内部,每个client连接都有自己的线程。这个连接的查询都在一个单独的线程中执行。这些线程轮流运行在某一个CPU内核(多核CPU)或者CPU中。服务器缓存了线程,因此不需要为每个client连接单独创建和销毁线程 。

    当clients(也就是应用程序)连接到了MySQL服务器。服务器需要对它进行认证(Authenticate)。认证是基于用户名,主机,以及密码。对于使用了SSL(安全套接字层)的连接,还使用了X.509证书。clients一连接上,服务器就验证它的权限 (如是否允许客户端可以查询world数据库下的Country表的数据)。

    优化和执行

    MySQL会解析查询,并创建了一个内部数据结构(解析树)。然后对其进行各种优化。这些优化包括了,查询语句的重写,读表的顺序,索引的选择等等。用户可以通过查询语句的关键词传递给优化器以便提示使用哪种优化方式,这样即影响了优化器的优化方式。另外,用户也可以请求服务器给出优化过程的各种说明,以获知服务器的优化策略,为用户提供了参数基准,以便用户可以重写查询,架构和修改相关服务器配置,便于mysql更高效的运行。

    优化器并是不关心表使用了哪种存储引擎,但是存储引擎对服务器优化查询的方式是有影响的。优化器需要知道存储引擎的一些特性:具体操作的性能和开销方面的信息,以及表内数据的统计信息。例如,存储引擎支持哪些索引类型,这对于查询是非常有用的。

    在解析查询之前,要查询缓存,这个缓存只能保存查询信息以及结果数据。如果请求一个查询在缓存 中存在,就不需要解析,优化和执行查询了。直接返回缓存中所存放的这个查询的结果。

    二.MySQL内存结构

    Mysql 内存分配规则是:用多少给多少,最高到配置的值,不是立即分配。

    实际上MySQL内存的组成和Oracle类似,也可以分为SGA(系统全局区)和PGA(程序缓存区)。

    mysql>show variables like "%buffer%";

    一、SGA

    1.innodb_buffer_pool

    用来缓存Innodb表的数据、索引、插入缓冲、自适应哈希索引,锁信息,数据字典等信息。

    2.innodb_log_buffer

    事务在内存中的缓冲,即red log buffer的大小

    3.query cache

    高速查询缓存,在生产环境中建议关闭。

    4.key_buffer_size

    用于MyISAM存储引擎,缓存MyISAM存储。

    引擎表的索引文件(区别于innodb_buffer_poll数据和索引缓存)

    5.innodb_additional_mem_pool_size

    用来缓存数据字典信息和其它内部数据结构的内存池的大小。MySQL5.7.4中该参数取消。

    二、PGA

    1.sort_buffer_size(排序缓冲大小,提高排序效率)

    主要用于SQL语句在内存中的临时排序

    2.join_buffer_size

    表连接使用,用于BKA,MySQL5.6之后开始支持。

    3.read_buffer_size(顺序读缓冲大小,提高顺序都效率)

    表顺序扫描的缓存,只能应用于MyISAM表存储引擎。

    4.read_rnd_buffer_size(随机缓冲大小,提高随机都效率)

    MySQL随机读缓冲区大小,用于做mrr,mrr是MySQL5.6之后才有的特性。

    5.tmp_table_size

    SQL语句在排序或分组时没有用到索引,就会使用临时表空间。

    6.max_heap_table_size

    管理heap,memory存储引擎表。


    1、全局内存(Global buffer)

    (1)innodb_buffer_pool_size:

    (1.1) innodb高速缓冲data和索引,简称IBP,这个是Innodb引擎中影响性能最大的参数。建议将IBP设置的大一些,单实例下,建议设置为可用RAM的50%~80%。
    (1.2)innodb不依赖OS,而是自己缓存了所有数据,包括索引数据、行数据等等,这个和myisam有差别。
    (1.3)IBP有一块buffer用于插入缓冲,在插入时,先写入内存之后再合并后顺序写入磁盘;在合并到磁盘的时候会引发较大的IO操作,对实际操作造成影响。(看上去的表现是抖动,TPS变低)
    (1.4)show global status like ‘innodb_buffer_pool_%’ 查看IBP状态,单位是page(16kb),其中,Innodb_buffer_pool_wait_free 如果较大,需要加大IBP设置
    (1.5)InnoDB会定时(约每10秒)将脏页刷新到磁盘,默认每次刷新10页;要是脏页超过了指定数量(innodb_max_dirty_pages_pct),InnoDB则会每秒刷100页脏页
    (1.6)innodb_buffer_pool_instances可以设置pool的数量
    (1.7)show engine innodb statusG    可以查看innodb引擎状态

     

    (2)innodb_additional_mem_pool_size:

    (2.1)指定InnoDB用来存储数据字典和其他内部数据结构的内存池大小。缺省值是8M(8388608)。通常不用太大,只要够用就行,应该与表结构的复杂度有关系。如果不够用,MySQL会在错误日志中写入一条警告信息。5.7版本已经弃用这个参数
    

    (3)innodb_log_buffer_size:

    (3.1)innodb redo日志缓冲,提高redo写入效率。如果表操作中包含大量并发事务(或大规模事务),并且在事务提交前要求记录日志文件,请尽量调高此项值,以提高日志效率。
    (3.2)show global status 查看 Innodb_log_waits 是否大于0,是的话,就需要提高 innodb_log_buffer_size,否则维持原样。
    (3.3)show global stauts 查看30~60秒钟 Innodb_os_log_written 的间隔差异值,即可计算出 innodb_log_buffer_size 设置多大合适。

    默认8M,一般设置为16 ~ 64M足够了。 
     
    (4)key_buffer_size:

    (4.1)myisam引擎中表的索引 的缓存大小,默认值=16M;单个key_buffer_size最大只有4G(32-bit系统下最大4G,64-bit下可以超过)
    (4.2)若主要使用myisam存储引擎,则设置最高不超过物理内存的20%~50%,
    (4.4)即便全是innodb表,没用MyISAM,也有必要设置key_buffer_size用于缓存临时表的索引,推荐设置32MB
    (4.5)关于临时表,如果内存tmp_table_size(Created_tmp_tables)不够的话,内部的临时磁盘表是MyISAM表(Created_tmp_disk_tables)。show global status like 'Create%'; show variables like 'tmp%';
    

    (5)query_cache_size :

     查询高速缓冲,缓存结果,减少硬解析(建议关闭,如果真需要查询缓存可以借助redis等缓存),最好是关闭
         
    

    (6)table_definition_cache:

       (6.1)表定义文件描述缓存,提高表打开效率。是frm文件在内存中的映射。MySQL需要打开frm文件,并将其内容初始化为Table Share 对象。这里存放与存储引擎无关的,独立的表定义相关信息。
    

    (7)table_open_cache:

    (7.1)表空间文件描述缓冲,提高表打开效率。
    (7.2)增加table_open_cache,会增加文件描述符(ulimit -a查看系统的文件描述符),当把table_open_cache设置的过大时,如果系统处理不了这么多文件描述符,那么就会出现客户端失效、连接不上。
    (7.3)table_open_cache,也就是平时说的table cache。存放当前已经打开的表句柄,与表创建时指定的存储引擎相关。请注意和table_define_cache参数的区别。
    

    为什么MySQL会出现table_open_cahce和table_define_cache这两个概念? 
    是因为:MySQL支持不同的存储引擎,每种存储引擎,数据存储的格式都是不一样的,因此需要指定一个存储引擎相关的handler。这就有了table cache的作用(table_open_cache参数)。另外表的定义也需要存放内存中,而表的定义frm文件每个存储引擎是通用的,需要另外独立开来,这就有了table definition cache。

    (8)max_heap_table_size和tmp_table_size:

    (8.1)max_heap_table_size 参数:定义了MEMORY、HEAP表的最大容量,如果内存不够,则不允许写入数据
    (8.2)tmp_table_size参数:规定了内部内存临时表的最大值,每个线程都要分配。(实际起限制作用的是tmp_table_size和max_heap_table_size的最小值。)如果内存临时表超出了限制,MySQL就会自动地把它转化为基于磁盘的MyISAM表,存储在指定的tmpdir目录下。
    (8.3)优化查询语句的时候,要避免使用临时表,如果实在避免不了的话,要保证这些临时表是存在内存中的,否则临时表超过内存临时表的限制,会自动转化为基于磁盘的Myisam表。

    2、线程内存(Thread buffer)

    (1)read_buffer_size:

    是MySQL读入缓冲区大小。对表进行顺序扫描的请求将分配一个读入缓冲区,MySQL会为它分配一段内存缓冲区。read_buffer_size变量控制这一缓冲区的大小。如果对表的顺序扫描请求非常频繁,并且你认为频繁扫描进行得太慢,可以通过增加该变量值以及内存缓冲区大小提高其性能。
    

    (2)read_rnd_buffer_size:

    是MySQL的随机读缓冲区大小。当按任意顺序读取行时(例如,按照排序顺序),将分配一个随机读缓存区。进行排序查询时,MySQL会首先扫描一遍该缓冲,以避免磁盘搜索,提高查询速度,如果需要排序大量数据,可适当调高该值。但MySQL会为每个客户连接发放该缓冲空间,所以应尽量适当设置该值,以避免内存开销过大。
    

    (3)sort_buffer_size:

    是MySQL执行排序使用的缓冲大小。如果想要增加ORDER BY的速度,首先看是否可以让MySQL使用索引而不是额外的排序阶段。如果不能,可以尝试增加sort_buffer_size变量的大小。
    

    (4)join_buffer_size:

    应用程序经常会出现一些两表(或多表)Join的操作需求,MySQL在完成某些 Join 需求的时候(all/index join),为了减少参与Join的“被驱动表”的读取次数以提高性能,需要使用到 Join Buffer 来协助完成 Join操作。当 Join Buffer 太小,MySQL 不会将该 Buffer 存入磁盘文件,而是先将Join Buffer中的结果集与需要 Join 的表进行 Join 操作,然后清空 Join Buffer 中的数据,继续将剩余的结果集写入此 Buffer 中,如此往复。这势必会造成被驱动表需要被多次读取,成倍增加 IO 访问,降低效率。
    

    (5)binlog_cache_size:

    在事务过程中容纳二进制日志SQL 语句的缓存大小。二进制日志缓存是服务器支持事务存储引擎并且服务器启用了二进制日志(—log-bin 选项)的前提下为每个客户端分配的内存,注意,是每个Client 都可以分配设置大小的binlog cache 空间。如果系统中经常会出现多语句事务的话,可以尝试增加该值的大小,以获得更好的性能。当然,我们可以通过MySQL 的以下两个状态变量来判断当前的binlog_cache_size 的状况:Binlog_cache_use 和Binlog_cache_disk_use。“max_binlog_cache_size”:和"binlog_cache_size"相对应,但是所代表的是binlog 能够使用的最大cache 内存大小。当我们执行多语句事务的时候,max_binlog_cache_size 如果不够大的话,系统可能会报出“ Multi-statement transaction required more than 'max_binlog_cache_size' bytes ofstorage”的错误。
    其中需要注意的是:table_cache表示的是所有线程打开的表的数目,和内存无关。
    

    (6)tmp_table_size:

    是MySQL的临时表缓冲大小。所有联表查询在一个DML指令内完成,并且大多数联合甚至可以不用临时表即可以完成。大多数临时表是基于内存的(HEAP)表。具有大的记录长度的临时表 (所有列的长度的和)或包含BLOB列的表存储在硬盘上。如果某个内部heap(堆积)表大小超过tmp_table_size,MySQL可以根据需要自动将内存中的heap表改为基于硬盘的MyISAM表。还可以通过设置tmp_table_size选项来增加临时表的大小。也就是说,如果调高该值,MySQL同时将增加heap表的大小,可达到提高联接查询速度的效果。
    

    (7)thread_stack :

    主要用来存放每一个线程自身的标识信息,如线程id,线程运行时基本信息等等,我们可以通过 thread_stack 参数来设置为每一个线程栈分配多大的内存。每个连接线程被创建时,MySQL给它分配的内存大小。当MySQL创建一个新的连接线程时,需要给它分配一定大小的内存堆栈空间,以便存放客户端的请求的Query及自身的各种状态和处理信息。 
    

    (8)thread_cache_size:

    如果我们在MySQL服务器配置文件中设置了thread_cache_size,当客户端断开之后,服务器处理此客户的线程将会缓存起来以响应下一个客户而不是销毁(前提是缓存数未达上限)。
    

    (9)net_buffer_length:

    客户发出的SQL语句期望的长度。如果语句超过这个长度,缓冲区自动地被扩大,直到max_allowed_packet个字节。
    

    (10)bulk_insert_buffer_size:

    如果进行批量插入,可以增加bulk_insert_buffer_size变量值的方法来提高速度,但是,这只能对myisam表使用。

    3、overhead

    (1)自适应哈希索引(Adaptive index hash)

    (1.1)哈希索引是一种非常快的等值查找方法(注意:必须是等值,哈希索引对非等值查找方法无能为力),它查找的时间复杂度为常量,InnoDB采用自适用哈希索引技术,它会实时监控表上索引的使用情况,如果认为建立哈希索引可以提高查询效率,则自动在内存中的“自适应哈希索引缓冲区”中建立哈希索引。
    (1.2)之所以该技术称为“自适应”是因为完全由InnoDB自己决定,不需要DBA人为干预。它是通过缓冲池中的B+树构造而来,且不需要对整个表建立哈希索引,因此它的数据非常快。
    (1.3)InnoDB官方文档显示,启用自适应哈希索引后,读和写性能可以提高2倍,对于辅助索引的连接操作,性能可以提高5被,因此默认情况下为开启,可以通过参数innodb_adaptive_hash_index来禁用此特性。
    (1.4)哈希索引总是基于表上已存在的B树索引来建立的。InnoDB会在为该B树定义的键的一个前缀上建立哈希索引,不管该键有多长。哈希索引可以是部分的:它不要求整个B树索引被缓存在缓冲池中。InnoDB根据需要对被经常访问索引的那些页面建立哈希索引。
    

    (2)System dictionary hash 
    (3)Locking system 
    (4)Sync_array 
    (5)Os_events






  • 相关阅读:
    python_day_5:20180720
    python_day_4:20180719
    2018悦读
    2018生活
    心理画
    js 策略模式
    js 单例模式
    js 模板方法模式
    C语言-数据类型
    js 观察者模式
  • 原文地址:https://www.cnblogs.com/asea123/p/10076563.html
Copyright © 2011-2022 走看看