Mysql性能优化、Mysql参数优化、Mysql配置优化

Mysql性能优化、Mysql参数优化、Mysql配置优化

Mysql参数优化对于不一样的网站,及在线量等,以及机器硬件的配置都有关系,优化不可能一次性完成,须要不断的观察以及调试,才有可能的获得最佳的效果html

为了测试咱们建立一个test1的库建立一个tb1的表,而后导入2万行数据,脚本以下:mysql

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/bash 
HOSTNAME= "localhost" 
PORT= "3306" 
USERNAME= "root" 
PASSWORD = "pwd123" 
DBNAME= "test1" 
TABLENAME= "tb1" 
# create database 
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${ PASSWORD } -e "drop database if exists ${DBNAME}" 
create_db_sql= "create database if not exists ${DBNAME}" 
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${ PASSWORD } -e "${create_db_sql}" 
# create table 
create_table_sql= "create table if not exists ${TABLENAME}(stuid int not null primary key,stuname varchar(20) not null,stusex char(1)  
not null,cardid varchar(20) not null,birthday datetime,entertime datetime,address varchar(100)default null)" 
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${ PASSWORD } ${DBNAME} -e "${create_table_sql}" 
# insert data to table 
i= "1" 
while [ $i -le 20000 ] 
do 
insert_sql= "insert into ${TABLENAME}  values($i,'zhangsan','1','21276387261874682','1999-10-10','2017-10-24','beijingchangpingqu')" 
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${ PASSWORD } ${DBNAME} -e "${insert_sql}" 
let i++ 
done 
# select data 
select_sql= "select count(*)from${TABLENAME}" 
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${ PASSWORD } ${DBNAME} -e "${select_sql}"
随后运行脚本直到运行结束为止(运行结束后查看是否插入成功)
?
1
2
3
4
5
6
7
mysql> select count (*) from test1.tb1;
+ ----------+
| count (*) |
+ ----------+
|    20000 |
+ ----------+
1 row in set (0.15 sec)

在手动插入一条其余数据。sql

?
1
2
mysql> insert into test1.tb1 values (20001, 'admin' , '0' , '12322112123332' , '1999-1-1' , '2019-9-1' , 'ppppppppppp' );
Query OK, 1 row affected (0.00 sec)

在没有优化以前咱们使用mysqlslap来进行压力测试数据库

?
1
2
3
4
[root@yankerp ~]# mysqlslap --defaults-file=/etc/my.cnf \
> --concurrency=100 --iterations=1 --create-schema='test1' \
> --query='select * from test1.tb1' engine=innodb \
> --number-of-queries=2000 -uroot -ppwd123 -verbose
\
咱们能够看到没有优化以前,它所用的时间为41.761秒,接下来开始咱们的配置优化

下面列出了对性能优化影响较大的主要变量,主要分为链接请求的变量和缓冲区的变量缓存

1) 链接请求的变量安全

Max_connections性能优化

Mysql的最大链接数,若是服务器的并发请求量比较大,能够调高这个值,固然这是要创建在机器可以支撑的状况下,由于若是链接数愈来愈多,mysql会为每一个链接提供缓冲区,就会开销的越多的内存,因此须要适当的调整该值,不能随便去提升设值。bash

?
1
Mysql>show variables like ‘max_connections’最大链接数
?
1
Mysql>show status like ‘max_user_connections’响应的链接数

若是max_used_connections跟max_connections相同那么就是max_connections设置太低或者超过服务器的负载上限了,低于10%则设置过大服务器

1.首先查看mysql默认的最大链接数(默认为151)session

?
1
2
3
4
5
6
7
mysql> show variables like "max_connections%" ;
+ -----------------+-------+
| Variable_name   | Value |
+ -----------------+-------+
| max_connections | 151   |
+ -----------------+-------+
1 row in set (0.02 sec)

修改/etc/my.cnf在[mysqld]下添加如下内容,设置最大链接数为1024,重启mysql服务验证

Max_connections=1024

查看修改后的最大链接数
?
1
2
3
4
5
6
7
mysql> show variables like "max_connections%" ;
+ -----------------+-------+
| Variable_name   | Value |
+ -----------------+-------+
| max_connections | 1024  |
+ -----------------+-------+
1 row in set (0.00 sec)
2)back_log

mysql能暂存的链接数量,当主要mysql线程在一个很短期内获得很是多的链接请求时候它就会起做用,若是mysql的链接数据达到max_connections时候,新来的请求将会被存在堆栈中,等待某一链接释放资源,该推栈的数量及back_log,若是等待链接的数量超过back_log,将不被授予链接资源

back_log值指出在mysql暂时中止回答新请求以前的短期内有多少个请求能够被存在推栈中,只有若是指望在一个短期内有不少链接的时候须要增长它

当咱们在观察主机进程列表

?
1
mysql>show full processlist
发现大量的 待链接进程时,就须要加大back_log或者加大max_connections的值
?
1
3 | root | localhost | NULL | Query   |    0 | starting | show full processlist
能够经过如下命令查看back_log的设置
?
1
2
3
4
5
6
7
mysql> show variables like 'back_log' ;
+ ---------------+-------+
| Variable_name | Value |
+ ---------------+-------+
| back_log      | 254   |
+ ---------------+-------+
1 row in set (0.00 sec)
修改/etc/my.cnf文件在[mysqld]下添加以下内容,设置最大链接数为1024,随后重启mysql服务再次查看
?
1
2
3
4
5
6
7
mysql> show variables like 'back_log' ;
+ ---------------+-------+
| Variable_name | Value |
+ ---------------+-------+
| back_log      | 1024  |
+ ---------------+-------+
1 row in set (0.00 sec)
3)wait_timeout和interactive_timeout

wait_timeout:指的是mysql在关闭一个非交互的链接以前所要等待的秒数
interactive_timeoutz:指的是mysql在关闭一个交互的链接以前所须要等待的秒数,好比咱们在终端上进行mysql管理,使用的即便交互的链接,这时候,若是没有操做的时间超过了interactive_time设置的时间就会自动的断开,默认的是28800,可调优为7200。wait_timeout:若是设置过小,那么链接关闭的就很快,从而使一些持久的链接不起做用
若是设置太大,容易形成链接打开时间过长,在show processlist时候,能看到不少的链接 通常但愿wait_timeout尽量低

查看wait_timeout和interactive_timeout的设置

?
1
mysql> show variables like "%wait_timeout%" ;
?
1
mysql> show variables like "%interactive_timeout%" ;
\

修改/etc/my.cnf,添加如下内容

wait_timeout=100
interactive_timeout=100

重启mysql服务,再次查看

\

4)key_buffer_size
key_buffer_size指定索引缓冲区的大小,它决定索引处理的速度,尤为是索引读的速度,经过key_read_requests和key_reads能够直到key_baffer_size设置是否合理。
能够经过show status like "key_read%"查看

?
1
2
3
4
5
6
7
mysql> show variables like "key_buffer_size%" ;
+ -----------------+---------+
| Variable_name   | Value   |
+ -----------------+---------+
| key_buffer_size | 8388608 |
+ -----------------+---------+
1 row in set (0.00 sec)
?
1
2
3
4
5
6
7
8
mysql> show status like "key_read%" ;
+ -------------------+-------+
| Variable_name     | Value |
+ -------------------+-------+
| Key_read_requests | 6     |
| Key_reads         | 3     |
+ -------------------+-------+
2 rows in set (0.01 sec)
一共有6个索引读取请求,有三个请求在内存中没有找到直接从硬盘中读取索引

key_buffer_size只对myisam表起做用,即便不使用myisam表,可是内部的临时磁盘表是myisam表,也要使用该值。可使用检查状态值created_tmp_disk_tables得知
?
1
2
3
4
5
6
7
8
9
mysql> show status like "created_tmp%" ;
+ -------------------------+-------+
| Variable_name           | Value |
+ -------------------------+-------+
| Created_tmp_disk_tables | 0     |
| Created_tmp_files       | 5     |
| Created_tmp_tables      | 0     |
+ -------------------------+-------+
3 rows in set (0.00 sec)
默认配置数值是8388608我主机有2个G内存那么可调优为134217728(128MB)
能够修改主配置文件添加以下内容

key_buffer_size=128M

重启mysql服务后再次查看

5)query_cache_size(查询缓存简称QC)
使用查询缓冲,mysql将查询结果存放在缓冲区中,从此对于一样的select语句(区分大小写),将直接从缓冲区中读取结果。
一个sql查询若是以select开头,那么mysql服务器将尝试对其使用查询缓存。
注:两个sql语句,只要想差哪怕是一个字符(列如大小写不同;多一个空格等),那么这两个sql将使用不一样的一个cache。
上述状态值可使用show status like 'Qcache%得到'
 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> show status like "%Qcache%" ;
+ -------------------------+---------+
| Variable_name           | Value   |
+ -------------------------+---------+
| Qcache_free_blocks      | 1       |
| Qcache_free_memory      | 1031832 |
| Qcache_hits             | 0       |
| Qcache_inserts          | 0       |
| Qcache_lowmem_prunes    | 0       |
| Qcache_not_cached       | 0       |
| Qcache_queries_in_cache | 0       |
| Qcache_total_blocks     | 1       |
+ -------------------------+---------+
8 rows in set (0.00 sec)
Qcache_free_blocks:缓存中相邻内存块的个数。若是该值显示较大,则说明Query Cache 中的内存碎片较多了,FLUSH QUERY CACHE会对缓存中的碎片进行整理,从而获得一个空闲块。
注:当一个表被更新以后,和它相关的cache blocks将被free。可是这个block依然可能存在队列中,除非是在队列的尾部。能够用FLUSH QUERY CACHE语句来清空free blocks
Qcache_free_memory:Query Cache 中目前剩余的内存大小。经过这个参数咱们能够较为准确的观察出当前系统中的Query Cache 内存大小是否足够,是须要增长仍是过多了。
Qcache_hits:表示有多少次命中缓存。咱们主要能够经过该值来验证咱们的查询缓存的效果。数字越大,缓存效果越理想。
Qcache_inserts:表示多少次未命中而后插入,意思是新来的SQL请求在缓存中未找到,不得不执行查询处理,执行查询处理后把结果insert到查询缓存中。这样的状况的次数越多,表示查询缓存应用到的比较少,效果也就不理想。固然系统刚启动后,查询缓存是空的,这很正常。
Qcache_lowmem_prunes:多少条Query 由于内存不足而被清除出Query Cache。经过“Qcache_lowmem_prunes”和“Qcache_free_memory”相互结合,可以更清楚的了解到咱们系统中Query Cache 的内存大小是否真的足够,是否很是频繁的出现由于内存不足而有Query 被换出。这个数字最好长时间来看;若是这个数字在不断增加,就表示可能碎片很是严重,或者内存不多。(上面的free_blocks和free_memory能够告诉您属于哪一种状况)
Qcache_not_cached:不适合进行缓存的查询的数量,一般是因为这些查询不是 SELECT 语句或者用了now()之类的函数。
Qcache_queries_in_cache:当前Query Cache 中cache 的Query 数量;
Qcache_total_blocks:当前Query Cache 中的block 数量;。
咱们再查询一下服务器关于query_cache的配置:


\

上图能够看出query_cache_type为off表示不缓存任何查询

各字段的解释:
query_cache_limit:超过此大小的查询将不缓存
query_cache_min_res_unit:缓存块的最小大小 ,query_cache_min_res_unit的配置是一柄”双刃剑”,默认是4KB,设置值大对大数据查询有好处,但若是你的查询都是小数据查询,就容易形成内存碎片和浪费。
query_cache_size:查询缓存大小 (注:QC存储的最小单位是1024 byte,因此若是你设定了一个不是1024的倍数的值,这个值会被四舍五入到最接近当前值的等于1024的倍数的值。)

query_cache_type:缓存类型,决定缓存什么样的查询,注意这个值不能随便设置,必须设置为数字,可选项目以及说明以下:

若是设置为0,那么能够说,你的缓存根本就没有用,至关于禁用了。

若是设置为1,将会缓存全部的结果,除非你的select语句使用SQL_NO_CACHE禁用了查询缓存。

若是设置为2,则只缓存在select语句中经过SQL_CACHE指定须要缓存的查询。

修改/etc/my.cnf,配置完后的部分文件以下:

query_cache_size=256M

query_cache_type=1

保存文件,从新启动MYSQL服务,而后经过以下查询来验证是否真正开启了:

\

6)max_connect_errors是一个mysql中与安全有关的计数器值,它负责阻止过多尝试失败的客户端以防止暴力破解密码等状况,当超过指定次数,mysql服务器将禁止host的链接请求,直到mysql服务器重启或经过flush hosts命令清空此host的相关信息 max_connect_errors的值与性能并没有太大关系。
修改/etc/my.cnf文件,在[mysqld]下面添加以下内容
max_connect_errors=20

修改完后重启mysql服务

7)sort_buffer_size
每一个须要进行排序的线程分配该大小的一个缓冲区。增长这值加速ORDER BY 或GROUP BY操做,Sort_Buffer_Size并非越大越好,因为是connection级的参数,过大的设置+高并发可能会耗尽系统内存资源。列如:500个链接将会消耗500*sort_buffer_size(2M)=1G内存
修改/etc/my.cnf文件,在[mysqld]下面添加以下:

sort_buffer_size=2M

8)max_allowed_packet=32M
mysql根据配置文件会限制,server接受的数据包大小。有时候大的插入和更新会受max_allowed_packet参数限制,致使写入或者更新失败,更大值是1GB,必须设置1024的倍数

9)join_buffer_size=2M
用于表间关联缓存的大小,和sort_buffer_size同样,该参数对应的分配内存也是每一个链接独享。

10)thread_cache_size = 300
服务器线程缓存,这个值表示能够从新利用保存在缓存中线程的数量,当断开链接时,那么客户端的线程将被放到缓存中以响应下一个客户而不是销毁(前提是缓存数未达上限),若是线程从新被请求,那么请求将从缓存中读取,若是缓存中是空的或者是新的请求,那么这个线程将被从新建立,若是有不少新的线程,增长这个值能够改善系统性能.经过比较 Connections 和 Threads_created 状态的变量,能够看到这个变量的做用。设置规则以下:1GB 内存配置为8,2GB配置为16,3GB配置为32,4GB或更高内存,可配置更大。服务器处理此客户的线程将会缓存起来以响应下一个客户而不是销毁(前提是缓存数未达上限)

\

试图链接到MySQL(无论是否链接成功)的链接数

?
1
2
3
4
5
6
7
8
9
10
mysql> show status like 'threads_%' ;
+ -------------------+-------+
| Variable_name     | Value |
+ -------------------+-------+
| Threads_cached    | 0     |
| Threads_connected | 1     |
| Threads_created   | 1     |
| Threads_running   | 1     |
+ -------------------+-------+
4 rows in set (0.00 sec)

Threads_cached :表明当前此时此刻线程缓存中有多少空闲线程。
Threads_connected :表明当前已创建链接的数量,由于一个链接就须要一个线程,因此也能够当作当前被使用的线程数。
Threads_created :表明从最近一次服务启动,已建立线程的数量,若是发现Threads_created值过大的话,代表MySQL服务器一直在建立线程,这也是比较耗资源,能够适当增长配置文件中thread_cache_size值。
Threads_running :表明当前激活的(非睡眠状态)线程数。并非表明正在使用的线程数,有时候链接已创建,可是链接处于sleep状态。

11.innodb_buffer_pool_size

对于InnoDB表来讲,innodb_buffer_pool_size的做用就至关于key_buffer_size对于MyISAM表的做用同样。InnoDB使用该参数指定大小的内存来缓冲数据和索引。对于单独的MySQL 数据库服务器,最大能够把该值设置成物理内存的80%。
?
1
mysql> show variables like 'innodb_buffer_pool_size' ;

设置innodb_buffer_pool_size

修改/etc/my.cnf文件,在[mysqld]下面添加以下内容

?
1
innodb_buffer_pool_size= 2048M

重启MySQL Server进入后,查看设置已经生效。

12. innodb_flush_log_at_trx_commit

主要控制了innodb将log buffer中的数据写入日志文件并flush磁盘的时间点,取值分别为0、一、2三个。0,表示当事务提交时,不作日志写入操做,而是每秒钟将log buffer中的数据写入日志文件并flush磁盘一次;1,则在每秒钟或是每次事物的提交都会引发日志文件写入、flush磁盘的操做,确保了事务的ACID;设置为2,每次事务提交引发写入日志文件的动做,但每秒钟完成一次flush磁盘操做。

实际测试发现,该值对插入数据的速度影响很是大,设置为2时插入10000条记录只须要2秒,设置为0时只须要1秒,而设置为1时则须要229秒。所以,MySQL手册也建议尽可能将插入操做合并成一个事务,这样能够大幅提升速度。

根据MySQL手册,在容许丢失最近部分事务的危险的前提下,能够把该值设为0或2。

13.innodb_thread_concurrency = 0
此参数用来设置innodb线程的并发数量,默认值为0表示不限制,若要设置则与服务器的CPU核数相同或是cpu的核数的2倍,建议用默认设置,通常为8.

14.innodb_log_buffer_size

此参数肯定些日志文件所用的内存大小,以M为单位。缓冲区更大能提升性能,对于较大的事务,能够增大缓存大小。

innodb_log_buffer_size=32M

15. innodb_log_file_size = 50M

此参数肯定数据日志文件的大小,以M为单位,更大的设置能够提升性能.

16. innodb_log_files_in_group = 3

为提升性能,MySQL能够以循环方式将日志文件写到多个文件。推荐设置为3

17.read_buffer_size = 1M
MySql 读入缓冲区大小。对表进行顺序扫描的请求将分配一个读入缓冲区,MySql会为它分配一段内存缓冲区。若是对表的顺序扫描请求很是频繁,而且你认为频繁扫描进行得太慢,能够经过增长该变量值以及内存缓冲区大小提升其性能。和 sort_buffer_size同样,该参数对应的分配内存也是每一个链接独享

18.read_rnd_buffer_size = 16M
MySql 的随机读(查询操做)缓冲区大小。当按任意顺序读取行时(例如,按照排序顺序),将分配一个随机读缓存区。进行排序查询时,MySql会首先扫描一遍该缓冲,以免磁盘搜索,提升查询速度,若是须要排序大量数据,可适当调高该值。但MySql会为每一个客户链接发放该缓冲空间,因此应尽可能适当设置该值,以免内存开销过大。
注:顺序读是指根据索引的叶节点数据就能顺序地读取所须要的行数据。随机读是指通常须要根据辅助索引叶节点中的主键寻找实际行数据,而辅助索引和主键所在的数据段不一样,所以访问方式是随机的。

19.bulk_insert_buffer_size = 64M
批量插入数据缓存大小,能够有效提升插入效率,默认为8M

20.binary log

log-bin=/usr/local/mysql/data/mysql-bin

binlog_cache_size = 2M //为每一个session 分配的内存,在事务过程当中用来存储二进制日志的缓存, 提升记录bin-log的效率。没有什么大事务,dml也不是很频繁的状况下能够设置小一点,若是事务大并且多,dml操做也频繁,则能够适当的调大一点。前者建议是--1M,后者建议是:即 2--4M

max_binlog_cache_size = 8M //表示的是binlog 可以使用的最大cache 内存大小

max_binlog_size= 512M //指定binlog日志文件的大小,若是当前的日志大小达到max_binlog_size,还会自动建立新的二进制日志。你不能将该变量设置为大于1GB或小于4096字节。默认值是1GB。在导入大容量的sql文件时,建议关闭sql_log_bin,不然硬盘扛不住,并且建议按期作删除。

expire_logs_days = 7 //定义了mysql清除过时日志的时间。

二进制日志自动删除的天数。默认值为0,表示“没有自动删除”。

mysqladmin flush-logs 也能够从新开始新的binarylog

相关优化参数总结:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
slow_query_log=1
slow_query_log_file = /usr/ local /mysql/data/slow_query_log
long_query_time=1
log-queries- not -using-indexes
max_connections=1024
back_log=128
wait_timeout=60
interactive_timeout=7200
key_buffer_size=256M
query_cache_size=256M
query_cache_type=1
query_cache_limit=50M
max_connect_errors=20
sort_buffer_size=2M
max_allowed_packet=32M
join_buffer_size=2M
thread_cache_size=200
innodb_buffer_pool_size=2048M
innodb_flush_log_at_trx_commit=1
innodb_log_buffer_size=32M
innodb_log_file_size=128M
innodb_log_files_in_group=3
log-bin=mysql-bin
binlog_cache_size=2M
max_binlog_cache_size=8M
max_binlog_size=512M
expire_logs_days=7
read_buffer_size=1M
read_rnd_buffer_size=16M
bulk_insert_buffer_size=64M
server-id=1
优化结束后,再次进行压力测试,查看效果

\

但愿对您有所帮助,再见!