6.1 基本架构
- 服务层
大多数基于网络的客户端/服务端工具都有这一层,这一层主要是处理连接和安全验证。
- 核心层
这层处理MySQL的核心业务。查询分析、优化、缓存和内存的函数;内建的视图,存储过程,触发器。
- 存储引擎层
存储引擎负责数据的存储和提取。核心层通过存储引擎的API与存储引擎通信,这样子就遮蔽了不同存储引擎的差异,使得这些差异对上层查询是透明的。存储引擎之间不会相互通信,只是简单地响应上层的查询。
6.2 选择版本
MySQL的发展经历了下面的几个里程碑。
- 1979年,创始人Monty Windenius写了最初的版本。
- 1996年,发布1.0版本。
- 1995-2000年,MySQL AB公司成立,引入BDB。
- 2000年,集成MyISAM和Replication。
- 2008年,MySQL AB被Sun收购,2009年推出5.1版本。
- 2009年,Oracle收购Sun,2010年12月推出5.5版本。
MySQL被Oracle收购后,MySQL创始人Monty Windenius主导开发了MariaDB,采用GPL授权许可,完全兼容MySQL,使用XtraDB存储引擎来代替MySQL的InnoDB存储引擎。
由于上面所述的历史原因,造成了现在有4个MySQL的版本。
- MySQL社区版:用户群体最大。
- MySQL企业版:收费。
- Percona Server版:新特性多。
- MariaDB版:国内用户不多。
建议开发者选择MySQL社区版,足够应付业务上的需求。
6.3 配置文件详解
在Linux中MySQL的配置文件是/etc/my.cnf。
6.4 软件优化
6.4.1 正确使用MyISAM和InnoDB存储引擎
在MySQL 5.1版本中,默认的存储引擎是MyISAM;到了MySQL 5.5、5.6版本,默认的存储引擎是InnoDB。
MyISAM基于ISAM(索引顺序访问方法),支持全文索引,但并非事务安全,不支持外键,使用表级锁。每个MyISAM表存有3个文件:FRM文件存放表结构,MYD文件存放数据,MYI存放索引。
InnoDB是事务性存储引擎,其支持行锁,InnoDB表的行锁也不是绝对的,如果它在执行一个更新的语句时没法确定更新的范围,也会锁表。InnoDB支持回滚、崩溃恢复、ACID事务控制,InnoDB存储它的表和索引在一张表空间,表空间可以包含多个文件。
MyISAM和InnoDB的主要区别如下。
- MyISAM支持表锁,InnoDB支持行锁。
- MyISAM是非事务安全型,InnoDB是事务安全型。
- MyISAM不支持外键,InnoDB支持外键。
6.4.2 正确使用索引
使用索引的一些原则。
- 给合适的列建立索引
在where子句中经常需要给检索的列建立索引,或者给连接子句中指定的列建立索引,而不是给select选择列表中的列建立索引。
- 索引列的值尽可能不同
对于有唯一性的值,索引的效果最好;如果有大量的重复值,索引的效率很差。
- 使用短索引
对字符类型的列建立索引,只要有可能,都应该指定前缀长度。
- 利用最左前缀
创建一个n列索引,本质上是MySQL创建了n个索引。多个索引可以起n个索引的作用,可以用索引中最左列的值来匹配,这样的列值叫做最左前缀。
- 使用like查询时索引会失效
尽量少使用like查询,对于百万、千万级的数据,可以采用专业的搜索软件来实现。
- 不能滥用索引
索引不是越多越好,使用索引需要恰到好处。过度使用索引会有下面的问题:索引会占用额外的磁盘空间,降低性能;当更新数据时索引必须更新,花费时间更长;有可能使MySQL选择到不是最优的索引,增加查询优化的时间。
6.4.3 避免使用select *
使用“select *”有下面的坏处:
- 在select语句执行的过程中,“select *”从数据库中返回的结果更多,降低了查询的速度。
- 过多的返回结果会增大服务器返回给App端的数据的传输量。过大的传输量很容易造成请求的失效。
6.4.4 字段尽可能地设置为NOT NULL
6.5 硬件优化
6.5.1 增加物理内存
MySQL读写数据最大的性能瓶颈就是磁盘IO,从减少磁盘IO方面提高性能是个重要的方向。通过加大物理内存可以采取提升文件系统性能,减少磁盘IO。另外,MySQL中也用了大量的内存来提高性能,配置参数如下。
- thread_cache_size:服务端线程缓存。
- sort_buffer_size:每个连接需要使用buffer时,分配的内存大小。
- query_cache_size:查询缓存的大小。
- query_cache_limit:单次查询缓冲区的大小。
6.5.2 增加应用缓存
把应用的热数据存储在缓存中,如果缓存中有数据就不需要到数据库读取数据,从而达到提高性能的目的。
应用的缓存有以下两种。
- 本地缓存:把数据放在服务器的内存或文件中。
- 分布式缓存:Redis(数据可以持久化)或Memcache。
6.5.3 用固态硬盘代替机械硬盘
6.5.4 SSD硬盘+SATA硬盘混合存储方案
6.6 架构优化
6.6.1 分表
当项目上线后,随着用户的增长,有些数据表的规模会以几何级增长,当数据达到一定规模后查询读取性能就下降很多,这时要考虑分表了。
- 水平拆分:把一张表的数据分别保存在不同的表。
- 垂直拆分:把一张表的字段分别保存在不同的表。
分表的存储引擎是MyISAM,可以利用MERGE存储引擎将拆分的表合并成一张表。如果是InnoDB,也能通过alter table命令把InnoDB变为MyISAM。
6.6.2 读写分离
随着App的不断迭代和推广,数据不断增多,数据库的压力也越来越大,对MySQL的基础优化可能达不到最终的效果。因此采取数据库的读写分离策略进行优化。
读写分离是把对数据库的读和写操作分开对应于主/从数据库服务器,主数据库提供写操作,从数据库提供读操作(可以有多个数据库)。因为大多数业务是以读为主,因此多个从数据库能有效减轻数据库的压力。
当主数据库进行写操作时,数据要同步到从数据库,这样才能有效保证数据库完整性。这称为数据库的主从复制。
MySQL主从复制基于主服务器在二进制日志(binlog)中跟踪所有对数据库的更改实现。因此要进行复制,必须在主服务器上启用二进制日志。
主从复制的延迟问题,一般来说从数据库的压力比主数据库大多了,非常容易导致延迟。
延迟的解决方案如下。
- 定位延迟的瓶颈,如果是因为IO压力大,那么可以考虑采用升级硬件的方案,如把硬盘更换为SSD硬盘。
- 如果是因为单线程从relaylog中执行MySQL语句导致延迟,可以采用MySQL 5.6以上版本的多线程方案,或者采用Tungsten为代表的第三方并行复制工具。
- 如果以上两种方案都不起作用,就要考虑采用分库策略。
6.6.3 分库
当数据规模不断增打,分表和读写分离可能都满足不了系统的性能需求,这时需要考虑分库,即把不同的数据表部署到不同的数据库集群上。
支持数据库分库的关系型数据库分布式处理软件Mycat,它以代理服务器的形式位于应用服务器与后台数据库之间,由于其是无状态,因此很容易部署MyCat集群实现负载均衡。对外开放的接口是MySQL通信协议,将应用服务器传过来的SQL语句按照路由的规则拆解转发到不同的后台数据库,并把结果汇总并返回。
MyCat可以把一个逻辑上的数据库和数据表对应到物理上真实的数据库和数据表,用户只需要按照逻辑上的结构操作相关数据就行,遮蔽了物理上的差异。
6.7 SQL慢查询优化
SQL慢查询是指执行超过一定时间的SQL查询语句,把这些SQL查询语句记录到慢查询日志,方便开发人员找出有性能问题的SQL,针对这些SQL查询语句进行分析调优。
配置选项中慢查询相关的3个参数如下。
- long_query_time:定义慢查询的时间,SQL查询语句执行时间大于该参数设置时间的SQL都会被记录下来,支持小于1秒的设置。
- slow_query_log:设置是否打开慢查询日志的开关。
- slow_query_log_file:设置慢查询日志文件的路径。
配置慢查询有两种方法。
- 通过命令行设置,立即生效,但是在MySQL服务重启后失效。
set global long_query_time=1;
set global slow_query_log=on;
set global slow_query_log_file='/data/slow.log';
- 在/etc/my.conf中新增下面的配置选项,重启MySQL服务后生效。
[MySQLd]
long_query_time=1
slow_query_log=on
slow_query_log_file=/data/slow.log
可以使用MySQL自带的工具mysqldumpslow分析慢查询日志,例如,查看最慢的前3个SQL查询的命令格式如下。
mysqldumpslow -t 3 /data/slow.log
开启慢查询日志后,可在系统状态中查看慢查询数。
show global status like '%slow%';
要分析慢查询语句,需要使用到MySQL的explain命令。
来源:oschina
链接:https://my.oschina.net/u/2470917/blog/3035585