mysql优化【转】

最近听讲了博森瑞老师的mysql优化公开课,这个是我整理的笔记。

现在说一下mysql的内存和I/O方面的两个特点。

一、 mysql内存特点:

1、  也有全局内存和每个session的内存(每个session类似于oracle的sga和pga),但是针对每个session的内存,我们不要给它分配过大。如果对每个session的内存分配过大,会造成oom的发生。在高并发下,增加物理内存就可以减少物理I/O。所以mysql的内存管理比oracle简单一些。

                   2、在oracle里面有library cache,用来缓存执行计划的。但是mysql不会缓存执行计划,mysql有类似于oracle的Qcache,Qcache是用来缓存sql语句的,但是在生产中建议关掉此功能,因为该功能很鸡肋,它的功能体现不了那么大的作用。

                   3、mysql的查询分析器很高效,mysql不缓存执行计划,但是并不会出现像oracle那种硬解析的问题。

                   4、对于内存方面的分配,如果是单实例的Mysql,建议分配50%到70%的物理内存给mysql。

                   二、mysql I/O方面的特点

mysql有binlog、undo log和redo log三个日志文件都是顺序写I/O的方式。mysql的数据文件是包含着随机写I/O和顺序写I/O的。

目前mysql有innodb和myisam存储引擎。有人可能会说myisam的存储引擎要比innodb的存储引擎快。其实并不是这样的。为什么这么说呢哈?innodb主要根据主键检索数据时很快,因为主键里包含行的数据信息,而且,对于innodb,它是双链表结构, 所以他很快就能找到数据。另外,Innodb既缓存数据文件,也缓存索引文件。但是针对myisam来说呢,myisam只缓存索引文件。所以,一个很简单的道理,你说是从内存读快,还是从磁盘读快。答案肯定是从内存读取快。所以结论就是,Innodb要比Myisam存储引擎快。

优化思路:

1、发现问题的过程

当数据库慢了,要搞清是什么问题导致系统慢了,是系统的问题,还是开发的问题,还是数据库的问题;

2、找到问题后,锁定问题瓶颈点;

         锁定瓶颈点的过程,分为两个层面。一个是系统层面,一个是数据库层面。

2.1 系统层面

系统层面就需要我们学习一些linux方面的知识,利用linux的知识,来锁定问题的瓶颈在哪。top命令可以看哪个进程占用cpu最高,查看负载,可以查看内存。

vmstat可以查看内存、cpu、i/o。

sar –u查看cpu

sar -d 查看io

-        sar -r查看内存的。

         2.2数据库层面

         现在Mysql默认存储引起是innodb。

1、  show engine innodb status

通过show innodb status看锁的情况,看数据有没有锁,有没有死锁,有没有事务状态,看看一些页的情况,看看现在有没有老页和新页的移动。

2、  slow log

看慢日志,制定时间,有好多工具可以分析慢日志(如percona公司的),找到top10最慢的sql(一般优先处理频率最高的前十条SQL语句)

                   也可以通过图形化的工具,找到最慢的sql,然后找开发沟通,商讨是在业务上更改呢,还是针对这条SQL来进行优化。我们的目的就是让sql越简单越好。

3、  show global status

                   show global status查看数据库整体的性能,看哪个点需要调整一下,看碎片是如何产生,碎片产生多少,如何清理碎片。看每秒钟产生的TPS有多少。

4、  show processlist

show processlist查看整个mysql链接的一个情况,注意看wait timeout 和inactive timeout ,主要减少不活跃的连接,这样可以把那些消耗的内存收回,从而防止omq的发生。

5、Pt-ioprofile

                   pt-ioprofile是第三方工具,查看innodb内部有哪些表是最活跃的,因为大部分的优化,都是在SQL瓶颈点。当我们锁定到这些表,我们就可以针对这些表做一些文章了,看这些表是否需要添加索引,是否进行碎片的整理。所以这个工具也很重要。

3、 优化方法的初定

我们锁定到了问题的瓶颈点了,就需要制定优化方案。

4、 制定优化方案。

5、优化方案的测试

我们不能因为优化一个问题点,影响其他的业务。所以锁定问题是从面到点,但是优化测试是从点到面。我们只要把这个点解决问题了,而不要影响全面。所以测试时一定要找测试环境,方案能真正在生产线上实施再实施。

6、方案的实施

7、问题解决了

一定要做好记录,想清楚为什么发生这样的问题,避免下次再发生。这也是考验一个人的好的学习方式。

在硬件角度的优化

         从系统bios层面

从系统bios层面,有个参数叫dapc,它表示每瓦的电能都能产生最大的功效,可以让cpu发挥它最大的功效。

在bios层面,还有个参数是内存频率,一定要调成max performance。

在bios层面还有一个cae处理器,当它处于闲置状态的时候,我们可以禁用处理器,使其处于最低的状态。

关于TPS高,业务高

关于TPS高,业务高的一个情况,这种情况一定要配置阵列卡,一定要配置cache模块和bbu模块。bbu模块是用来提供我后备的电量,当机器断电了,我的bbu模块可以去充当电源,保证数据不会丢失,使数据写到cache里面。现在新的服务器都是电容模式的bbu了,性能会更好。

关于阵列卡策略的问题

         关于阵列卡策略的问题,一定要选择wb(write bike),就是当写数据的时候,一定要先写到cache卡里面,然后通过阵列卡把数据刷到磁盘,这样能提高我们的IOPS。一定要禁用wthrow,因为这种直接写磁盘是非常耗性能的。

         关于关闭预读功能

         关于关闭预读功能,就是让缓存踏踏实实做写缓存的作用。不要开启预读,不要开启数据页,到我的cache里面,这么做没有任何作用。

         关于阵列级别的选择

         关于阵列级别的选择,对于mysql数据库,建议用raid 1+0。

有人说,用raid5也不错,但是raid5的写乘法数据是4。为什么是4呢,因为raid5有读数据,读校验位、写数据,写校验位。但是raid10,它只有双写,也就是raid10的系数是2。所以raid10写的i/o一定要比raid5高,不过raid5读i/o比raid10可能好一些,但是针对oltp这种系统,推荐用raid10。

关于磁盘上的策略

关于关闭磁盘上的策略,一定要关闭磁盘上的cache策略。因为我们没有必要开它,这样可以防止丢失数据。

关于选盘的问题

建议上SSD或PCIE-SSD的磁盘,这样可以提高iops上百倍或者上千倍。

        

关于swappiness值大小的调整

         swappiness值大小对于我们如何使用swap分区是有很多联系的。当swappiness设置为0,就是充分利用虚拟内存。当swappines设置为100,表示能用swap分区,就用swap分区。

         在redhat 6版本之前,swappiness可以设置成0,;但是大于redhat6最好设置成10;到了redhat 7以上,一定要谨慎设置swappiness设置成0,因为如果设置成0了,在redhat 7可能会发生omq。

关于I/O调度器的选择

IO调度器,首选deadline,其次用noop,不要用默认的cfq,默认是非常的不好的。

关于文件系统的选择

         首先xfs,其次ext4。

i

############

innodb是Mysql的默认存储引擎。影响innodb引擎最重要的参数是innodb_buffer_pool_size,它就相当于oracle的buffer cache,是用来缓存数据用的。

在单实例的mysql,最好设置innodb_buffer_pool_size设置为50%~70%的物理内存大小。

innodb_data_file_path,该参数就是分配共享表空间的大小。它默认是10m。但是我们建议将其设置成1G,这样可以避免后期数据暴涨很消耗性能。

innodb_log_file_size,该参数不要设置的过大,因为该参数相当于oracle里面的redo。如果把该参数设置的过大,当数据库crash的时候,恢复数据就会很慢。

transaction_isolation,表示事务隔离级别。对于mysql需要什么样的事务隔离级别,是需要一步一步去选择的。对于oracle来讲,事务隔离级别就是默认的提交读。但是对于mysql,有默认的提交读,也有可重复读,还有脏读和串读。建议使用Mysql的可重复读(r模式),因为这种模式可以保证数据的一致性,可以避免发生一个事务提交了,在另一个事务中能看到他提交的东西。如果事务提交了,在另外一个事务中能看到他提交的东西,这样就违背了事务一致性的情况的。

  sort_buffer_size、read_buffer_size、join_buffer_size三个参数,可以理解为oracle的pga。这三个参数不用设置过大,大概几兆,几十兆就行。另外oracle的pga也不要设置的过大。

         general_log,log_bin,sync_binlog,long_query_time,interactive_timeout,wait_timeout,max_connections

         在生产上,不要开全日志(general_log),因为开了全日志,它就会记录全部的sql语句,这样很影响mysql性能。

         对于binlog日志,一定要开此功能,因为这样可以实现复制的功能,也可以实现binlog恢复的功能。

         对于sync_binlog,该参数数值的大小,关系到数据库写binlog情况的问题。sync_binlog=0,表示我每一秒刷一次binlog,sync_binlog=1表示每秒我都刷,保证他不会丢;当sync_binlog=2,表示交给操作系统,数据库不管了。

         对于long_query_time,表示慢查询时间的一个情况,可以设置0.xxxx秒的慢查询。对出现频率高的慢sql进行优化。

可以通过show processlist看一些交互式和非交互式的时间等待。对于interactive_timeout和wait_timeout这两个参数我们不要设置的过大,一般这两个值设置的一样,在没有连接池的情况,设置成5分钟就行了。

         max_connections,当用户连接数超过这个max_connections时,会报错。但注意,报错时,不要盲目的增大max_connections这个参数。因为如果max_connections设置的过大,会发生数据库被连暴了,塌了的情况,是很危险。那么我们应该如何调整呢?其实出现这种情况会联系到好多的参数的,比如可以减少并发参数的值来减少连接数,或者观察数据库sql语句,分析到底是业务的问题还是数据库的问题。不要什么事情都往自己身上揽,拿出证据,证明这个问题就不是我DBA的问题。

        

        

选择存储引擎,是针对业务来讲。针对oltp 默认就是Innodb。到了mysql 5.7有可能myisam会消失。

         innodb存储引擎支持事务,支持行锁,锁的粒度更低,所以并发性很好,当发生故障可以根据redo和Undo进行恢复。Innodb是缓存数据和索引的,但是Myisam只缓存索引,而且myisam的数据和索引是分开的。

一定要设置自增主键。如果你不设置自增主键,也没有关系,这时候Mysql会给它一个6字节的主键,但是这样会很消耗性能的。所以设置自增主键是一个必须的选项。

关于时间日期,ipv4类型和数据类型可以用int

避免使用text/blob这种大数据类型。如果非要用大数据类型,可以单独把大数据类型放在一张表上存储。

定义字段的时候尽量要定义Not null,因为索引是不含Null字段的。

选择性低的字段不要创建索引,像男女这样的字段不要创建索引,创建索引没有意义。因为mysql优化器是很智能的,重复值出现很多,mysql可能就不走索引,而是走全表扫描了。

对于排序和分组字段上,一定要创建索引。

索引不要太多,因为update,会使索引的页进行翻转,对性能有很大的下降。

联合索引优于单列索引,联合索引可以缩短整个段池搜索的一个范围,它比单列索引要好。

像一些字符类型,如果可能只用到前面几个字符,而不需要整个字段建索引,这叫前缀索引,我们可以建立一个前缀索引,我只搜那几个字段。

         索引扫描记录的述超过30%,就会走全表扫描

模糊匹配查询的双%%不会用到索引的。但是去掉左边的%,%号在最后一位可能会用到索引。

联合索引,第一个查询条件如果不是最做索引列,也不会用到索引,这就是最左前缀原则。

联合索引,如果第一个索引列使用范围查询(> 、=、<、>=、<=),那用到索引也是部分索引,有可能只用到第一个索引了,后面的索引数据库都用不到。

两个独立的索引,一个用来检索,一个用来排序,可能只用到一个。mysql 5.6有ITC这项功能。

最忌讳在索引的字段上使用函数,这样是不会走索引的。

Q&A

         sga是内存全局区,pga是用户的一个session连接上数据库单独分配给的内存。

mysql用的最多的集群是MHA。oracle的集群是RAC。

为什么会产生死锁?就是因为共抢一块东西,你要我的东西,我又要你的东西,从而造成死循环,用show innodb status定位死锁产生在哪。

最好关闭磁盘的cache策略,因为写在cache里面,容易发生数据丢失,所以建议关闭磁盘的cache策略。

有问题留言,

保证业务的稳定,保证数据库快速。

主从分离和DBA没有关系,只需要开发在代码里面写好了。

现在mysql架构,就是用MHA。

不是说数据量大了,就进行优化,而是出现性能问题了再进行优化。看索引建没建。

转自

mysql优化--博森瑞-czxin788-ITPUB博客
http://blog.itpub.net/28916011/viewspace-1758440/

原文地址:https://www.cnblogs.com/paul8339/p/7779294.html