Mysql的体系结构
本章主要对MySQL体系结构做了详细的解读,包括不同语言与SQL的交互、系统管理和控制工具、连接池、SQL接口、解析器、查询优化器、查询缓存。
3.1 体系结构图
了解MySql必须牢牢记住其体系结构图,Mysql是由SQL接口,解析器,优化器,缓存,存储引擎组成的。
1、Connectors指的是不同语言中与SQL的交互
2、Management Serveices & Utilities:系统管理和控制工具
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:查询缓存
如果查询缓存有命中的查询结果,查询语句就可以直接去查询缓存中取数据。
这个缓存机制是由一系列小缓存组成的。比如表缓存,记录缓存,key缓存,权限缓存等。
8、Engine :存储引擎
存储引擎是MySql中具体的与文件打交道的子系统。也是Mysql最具有特色的一个地方。
3.2 Mysql缓存
众所周知,系统读取数据时,从内存中读取要比从硬盘上速度要快好几百倍。故现在绝大部分应用系统,都会最大程度的使用缓存(内存中的一个存储区域),来提高系统的运行效率。MySQL数据库也不例外。简单的说,数据缓存就是内存中的一块存储区域,其存储了用户的SQL文本以及相关的查询结果。通常情况下,用户下次查询时,如果所使用的SQL文本是相同的,并且自从上次查询后,相关的纪录没有被更新过,此时数据库就直接采用缓存中的内容。
我们可以在Mysql的配置文件里设置查询缓存。只要将query_cache_type设为1即可。在设置了这个属性后,MySQL在执行任何SELECT语句之前,都会在它的缓冲区中查询是否在相同的SELECT语句被执行过,如果有,并且执行结果没有过期(使用LRU算法),那么就直接取查询结果返回给客户端。但在写SQL语句时注意,MySQL的查询缓冲是区分大小写的。
虽然不设置查询缓冲,有时可能带来性能上的损失,但有一些SQL语句需要实时地查询数据,或者并不经常使用(可能一天就执行一两次)。这样就需要把缓冲关了。当然,这可以通过设置query_cache_type的值来关闭查询缓冲,但这就将查询缓冲永久地关闭了。在MySQL 5.0中提供了一种可以临时关闭查询缓冲的方法:当我们执行 select id,name from tableName; 这样就会用到查询缓存。在 query_cache_type 打开的情况下,如果你不想使用缓存,需要指明select sql_no_cache id,name from tableName;以上的SQL语句由于使用了sql_no_cache,因此,不管这条SQL语句是否被执行过,服务器都不会在缓冲区中查找,每次都会执行它。
我们还可以将my.ini中的query_cache_type设成2,这样只有在使用了SQL_CACHE后,才使用查询缓冲:
select sql_cache * from tableName;
mysql> show variables like '%query_cache%';
+------------------------------+---------+
| Variable_name| Value|
+------------------------------+---------+
| have_query_cache| YES|
| query_cache_limit| 2097152 |
| query_cache_min_res_unit| 512|
| query_cache_size| 134217728 |
| query_cache_type| ON|
| query_cache_wlock_invalidate | OFF|
have_query_cache 表示是否支持查询缓存区,“YES”表示支持查询缓存区;query_cache_limit表可缓存的Select查询结果的最大值1048576 byte /1024 = 1024kB 即最大可缓存的select查询结果必须小于1024KB ;query_cache_min_res_unit 表每次给query cache结果分配内存的大小,默认是4096 byte 也即4kB 。如果query_cache_size设置为0了,等同于没有使用缓存是一样的。
4711版本的EPG的配置项如上,使用部分mysql的缓存,大多还是使用EPG自身的缓存,仅仅是count(*)的查询是使用的mysql查询。后面详细介绍具体参数意义。
3.3 存储引擎
存储引擎就是如何存储数据、如何为存储的数据建立索引和如何更新、查询数据等技术的实现方法。因为在关系数据库中数据的存储是以表的形式存储的,所以存储引擎也可以称为表类型(即存储和操作此表的类型)。
在Oracle 和SQL Server等数据库中只有一种存储引擎,所有数据存储管理机制都是一样的。而MySql数据库提供了多种存储引擎。用户可以根据不同的需求为数据表选择不同的存储引擎,用户也可以根据自己的需要编写自己的存储引擎。
Mysql的存储引擎是插件式的。它根据MySql AB公司提供的文件访问层的一个抽象接口来定制一种文件访问机制(这种访问机制就叫存储引擎)。
3.3.1 常见的存储引擎
现在有很多种存储引擎,各个存储引擎的优势各不一样,最常用的有:MyISAM、InnoDB、MERGE、MEMORY(HEAP)、BDB(BerkeleyDB)、EXAMPLE、FEDERATED、ARCHIVE、CSV、BLACKHOLE。
默认下MySql是使用MyISAM引擎,它查询速度快,有较好的索引优化和数据压缩技术。但是它不支持事务。
InnoDB支持事务,并且提供行级的锁定,应用也相当广泛。 Mysql也支持自己定制存储引擎,甚至一个库中不同的表使用不同的存储引擎,这些都是允许的。MySQL支持数个存储引擎作为对不同表的类型的处理器。MySQL存储引擎包括处理事务安全表的引擎和处理非事务安全表的引擎:MyISAM管理非事务表。它提供高速存储和检索,以及全文搜索能力。MyISAM在所有MySQL配置里被支持,它是默认的MySQL存储引擎,除非你配置MySQL默认使用另外一个引擎。
MyISAM:默认的MySQL插件式存储引擎,它是在Web、数据仓储和其他应用环境下最常使用的MySQL存储引擎之一。注意,通过更改STORAGE_ENGINE配置变量,能够方便地更改MySQL服务器的默认存储引擎。
InnoDB:用于事务处理应用程序,具有众多特性,包括ACID事务支持。
BDB:可替代InnoDB的事务引擎,支持COMMIT、ROLLBACK和其他事务特性。
Memory:将所有数据保存在RAM中,在需要快速查找引用和其他类似数据的环境下,可提供极快的访问。
Merge:允许MySQL DBA或开发人员将一系列等同的MyISAM表以逻辑方式组合在一起,并作为1个对象引用它们。对于诸如数据仓储等VLDB环境十分适合。
Archive:为大量很少引用的历史、归档、或安全审计信息的存储和检索提供了完美的解决方案。
Federated:能够将多个分离的MySQL服务器链接起来,从多个物理服务器创建一个逻辑数据库。十分适合于分布式环境或数据集市环境。
Cluster/NDB:MySQL的簇式数据库引擎,尤其适合于具有高性能查找要求的应用程序,这类查找需求还要求具有最高的正常工作时间和可用性。
Other:其他存储引擎包括CSV(引用由逗号隔开的用作数据库表的文件),Blackhole(用于临时禁止对数据库的应用程序输入),以及Example引擎(可为快速创建定制的插件式存储引擎提供帮助)。
3.3.2 MyISAM和InnoDB比较
InnoDB和MyISAM是在使用MySQL最常用的两个表类型,各有优缺点,视具体应用而定。基本的差别为:MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持。MyISAM类型的表强调的是性能,其执行数度比InnoDB 类型更快,但是不提供事务支持,而InnoDB提供事务支持已经外部键等高级数据库功能(外键指的是一个表的主键作为另外一个表的字段)。
移值性:
MyISAM类型的二进制数据文件可以在不同操作系统中迁移。也就是可以
直接从Windows系统拷贝到linux系统中使用。
MyIASM是IASM表的新版本,有如下扩展:
二进制层次的可移植性。 NULL列索引。对变长行比ISAM表有更少的碎片。
支持大文件。更好的索引压缩。更好的键吗统计分布。更好和更快的auto_increment处理。
支持全文搜索,不过它们是事务不安全的,而且也不支持外键。如果事务回滚将会造成不完全回滚,从而不具备原子性。
读锁和写锁是互斥的,从而读写操作是串行的,MyISAM表不太适合于有大量更新操作和查询操作应用的原因。因为,大量的更新操作会造成查询操作很难获得读锁,从而可能永远阻塞。
数据行锁定:不支持,只有表锁定
以下是一些细节和具体实现的差别:
1.InnoDB不支持FULLTEXT类型的索引。
2.InnoDB中不保存表的具体行数,也就是说,执行select count(*) from table时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count(*)语句包含 where条件时,两种表的操作是一样的。
3.对于auto_increment类型的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中,可以和其他字段一起建立联合索引。
4.DELETE from table时,InnoDB不会重新建立表,而是一行一行的删除。
5.LOAD table from master操作对InnoDB是不起作用的,解决方法是首先把InnoDB表改成MyISAM表,导入数据后再改成InnoDB表,但是对于使用的额外的InnoDB特性(例如外键)的表不适用。
.frm存储数据表的框架结构,与表一一对应,不区分操作系统和数据引擎
MyISAM:*.MYD为数据文件,*.MYI为索引文件,*.log日志文件
InnoDB:所有表共用的数据、索引文件ibdata1、ibdata2, InnoDB:单个表表空间文件*.ibd,存放用户表数据和索引。通过配置项basedir、datadir指向具体目录,InnoDB可通过配置项innodb_data_home_dir修改
InnoDB日志文件:ib_logfile1、ib_logfile2,缺省与数据文件目录一致,可通过配置项innodb_log_group_home_dir指向具体目录
如果你的数据执行大量的INSERT或UPDATE,出于性能方面的考虑,同样应该使用InnoDB表。
对于支持事务的InnoDB类型的表来说,影响速度的主要原因是autocommit默认设置是打开的,而且程序没有显式调用BEGIN 开始事务,导致每插入一条都自动提交,严重影响了速度。可以在执行sql前调用begin,多条sql形成一个事物(即使autocommit打开也可以),将大大提高性能。
查看autocommit:select @@autocommit;或show variables like 'autocommit';
设置autocommit:set autocommit=0;
MyISAM和InnoDB存储引擎性能差别并不是很大,针对InnoDB来说,影响性能的主要是innodb_flush_log_at_trx_commit这个选项,如果设置为1的话,那么每次插入数据的时候都会自动提交,导致性能急剧下降,应该是跟刷新日志有关系,设置为0效率能够看到明显提升,当然,同样你可以SQL中提交“SET AUTOCOMMIT = 0”来设置达到好的性能。
InnoDB配置
innodb_additional_mem_pool_size = 16M
---InnoDB存储元数据信息时的额外的内存池。如果需要更多的内存,InnoDB为此它会分配它的操作系统内存。因为在大多数操作系统中,这已经是足够快的了,所以通常不需要修改这个值。SHOW INNODB STATUS会显示当前的使用量
innodb_buffer_pool_size = 600M
--这是InnoDB最重要的设置,对InnoDB性能有决定性的影响。这个磁盘I/O设置的更大,需要访问的数据表更少。在专用的数据库服务器上你可以设置参数高达80%的机器的物理内存大小。不用把它设置的太大,不过,因为在操作系统中竞争的物理内存可能导致内存不够分。注意,32位系统上的你可能被限制在2 - 3.5g的用户级内存,所以不要设置的太高。
innodb_data_file_path = ibdata1:2048M;ibdata2:2048M;ibdata3:1024M:autoextend
--用来容纳InnoDB为数据表的表空间: 可能涉及一个以上的文件; 每一个表空间文件的最大长度都必须以字节(B)、兆字节(MB)或千兆字节(GB)为单位给出; 表空间文件的名字必须以分号隔开; 最后一个表空间文件还可以带一个autoextend属性和一个最大长度(max:n)。例如,ibdata1:1G; ibdata2:1G:autoextend:max:2G的意思是: 表空间文件ibdata1的最大长度是1GB,ibdata2的最大长度也是1G,但允许它扩充到2GB
innodb_data_home_dir = /usr/local/mysql/data
--InnoDB主目录,所有与InnoDB数据表有关的目录或文件路径都相对于这个路径。在默认的情况下,这个主目录就是MySQL的数据目录。
innodb_write_io_threads = 8
---用于写脏页的线程数
innodb_read_io_threads = 8
---用于从磁盘读文件块的线程数
innodb_force_recovery=0
--强制启动mysql,当innodb表空间损坏时候,启动不了,可以强制启动;默认为0,表示当需要恢复时执行所有的恢复操作(即校验数据页/purge undo/insert buffer merge/rolling back&forward).当不能进行有效的恢复操作时,mysql有可能无法启动,并记录下错误日志.
innodb_thread_concurrency = 16
--InnoDB的内核允许多线程个数。最高性能取决于高的应用程序、硬件以及操作系统。但是一个很高的值可能导致线程抖动
innodb_flush_log_at_trx_commit = 2
--这个选项决定着什么时候把日志信息写入日志文件以及什么时候把这些文件物理地写(术语称为”同步”)到硬盘上。设置值0的意思是每隔一秒写一次日志并进行同步,这可以减少硬盘写操作次数,但可能造成数据丢失;设置值1的意思是在每执行完一条COMMIT命令就写一次日志并进行同步,这可以防止数据丢失,但硬盘写操作可能会很频繁; 设置值2是一般折衷的办法,即每执行完一条COMMIT命令写一次日志,每隔一秒进行一次同步。
innodb_log_buffer_size = 3M
--InnoDB的用于的缓冲日志数据的大小。一旦它满了,InnoDB会在磁盘上释放它。它无论如何都会一秒缓冲一次,这对于非常大的日志是没有意义的。(即使有长事务)
innodb_log_file_size = 256M
--每个日志文件在日志组里的大小,可设置为25%-90%的总体缓存大小,默认256M. 修改此项要先删除datadir\ib_logfileXXX
innodb_log_files_in_group = 3
--日志组中日志文件个数,默认是3。InnoDB数据表驱动程序将以轮转方式依次填写这些文件; 当所有的日志文件都写满以后,之后的日志信息将写入第一个日志文件的最大长度(默认设置是5MB)。这个长度必须以MB(兆字节)或GB(千兆字节)为单位进行设置。
innodb_max_dirty_pages_pct = 90
--InnoDB最大允许的脏页缓冲池的百分比,默认90
innodb_lock_wait_timeout = 120
--如果某个事务在等待n秒(s)后还没有获得所需要的资源,就使用ROLLBACK命令放弃这个事务。这项设置对于发现和处理未能被InnoDB数据表驱动程序识别出来的死锁条件有着重要的意义。这个选项的默认设置是50s。
lower_case_table_names = 1
--让Mysql不区分大小写的配置项。0表示区分大小写,1表示不区分大小写。
3.4.4 其他的配置
[mysqldump]
quick
--该选项在导出大表时很有用,它强制 mysqldump 从服务器查询取得记录直接输出而不是取得所有记录后将它们缓存到内存中。
max_allowed_packet = 16M
--包或任何生成的/中间字符串的最大大小。这个过程大部分发生在load data file中,有时也发生在update,insert中。
[mysql]
no-auto-rehash
--这个配置段设置启动MySQL服务的条件;在这种情况下,no-auto-rehash确保这个服务启动得比较快。等同于:mysql -A -S /tmp/mysql.sock参数。
[myisamchk]
key_buffer_size = 128M
sort_buffer_size = 2M
read_buffer = 2M
write_buffer = 2M
--类似前面的介绍
[mysqlhotcopy]
interactive-timeout
--服务器关闭交互式连接前等待活动的秒数。
[mysqld_safe]
open-files-limit = 8192
--指mysql能够打开的文件句柄数。该值不足时,会引发 Too many open files错误。具体需要多少个文件句柄,还需要根据 max_connections 和 table_open_cache来计算。open-files-limit可能受到操作系统的限制,比如linux中有一个参数可能会限制系统最大打开文件数值,就是/etc/security/limits.conf
转载于:https://blog.51cto.com/7633061/1275117