vlambda博客
学习文章列表

MYSQl深入探索系列四 服务端优化

目录

  1. 环境准备

  2. 常见innodb存储引擎常见参数及调优

  3. 压测优化后的数据库

1,环境准备

一台linux Centos7.6,2路12核 256G 5TSAS存储 980GSSD系统盘的物理机。mysql安装包mysql-5.7.36.tar.gz,xshell 5.x 客户端。下面我们来简单搭建下。


$ tar -zxvf mysql-5.7.36.tar.gz  #解压安装tar.gz$ mv mysql-5.7.36 mysql          #更改文件名称$ cd mysql$ mv ../etc/my.cnf ../etc/mysql_8901.cnf  # 重新命名配置文件,以端口结尾$ vi ../etc/mysql_8901.cnf       #更改数据路径到数据盘,以及binlog路径,暴露端口

  

修改的参数如下:

user=appsreport-host=192.168.1.108report-port=8901server-id=1088901 命名规则:机器ip后两个+端口port=8901socket=/tmp/mysql_8901.sockdatadir = /data1/apps/lv/mysql_data_8901/data/databasedir = /data1/apps/lv/mysql_exec_8901secure_file_priv = /data1/apps/lv/mysql_data_8901/data/datalog_error = /data1/apps/lv/mysql_data_8901/data/logs/error.logslow_query_log_file=/data1/apps/lv/mysql_data_8901/data/logs/slow.loglog_bin = /data1/apps/lv/mysql_data_8901/data/binlog/mysql-bin.logrelay_log=/data1/apps/lv/mysql_data_8901/data/relaylog/relay-bin.log


启动数据库

$ /home/lv/mysql/bin/mysqld_safe --defaults-file=/home/lv/mysql/etc/mysql_8901.cnf &

检查日志是否有报错

$ tailf /data1/apps/lv/mysql_data_8901/data/logs/error.log

如果没有报错直接使用root登录,初始的时候没有密码指定sock登录


$  /home/lv/mysql/bin/mysql -uroot -S /tmp/mysql_8901.sock登陆成功后执行:mysql> select @@version; +--------------+ | @@version | +--------------+ | 5.7.36-log | +--------------+ 1 row in set (0.00 sec)

至此 搭建完毕,创建相应的用户,更改root密码即可。

2,常见innodb存储引擎常见参数及调优

上面我们虽然简单搭建好了服务端,但是并没有做任何实质性的优化。都是默认参数,性能很差劲,接下来我们看下有哪些参数需要优化:

  • innodb_buffer_pool_size:innodb缓存池总大小

  • innodb_buffer_pool_instances:innodb缓存池实例数

  • innodb_flush_neighbors:   flush脏缓存页的时候是否flush相临的缓存页

  • thread_pool_size:线程池核心线程数

  • innodb_io_capacity:innodb flush到磁盘的速度


这几个参数实际作用是啥呢?继续往下看


mysql的innodb存储引擎 中缓存机制,即innodb_buffer_pool,mysql所有的操作都是先经过buffer_pool,如果缓存中没有就从磁盘中加载到缓存页中,所有的crud都是在缓存页中执行的,然后在合适的时间将脏的缓存页flush到磁盘上。


感觉就好像java执行业务逻辑时操作的redis一样是吧,那这个参数是不是越大越好呢?也不是,mysql官方给出的建议是服务器总内存的60%-70%左右,需要留出一部分内存空间给系统和其他进程使用。


而且缓存池越大后面维护成本也不一样,我们本次设置的是100G。这样就完了么?按照我们常规开发思想,一个redis性能强,还是多个redis组成的集群性能强?肯定多个啊,可以充分利用多核CPU,提高并发度,和吞吐量,那对于buffer_pool来说也是一样的。


我们通过innodb_buffer_pool_instances 来设置缓存池的个数,默认是8个。这里最好和cpu核数设置一致。我们设置的48。


我们执行数据库crud的时候都是在缓存池中操作的,这样会有源源不断的脏页需要刷到磁盘上,但是这个速度怎么控制呢?机械盘和ssd的io性能肯定不一致,我们可以通过innodb_io_capacity调整这个速度,根据自己的服务器磁盘性能合理的设置最优值,最好与磁盘的iops设置一致,这样可以充分发送磁盘最大性能。


这样就完了么?不不,我们都知道innodb在读取磁盘的时候为了提高性能,会进行预读也就是会把数据页相邻的几页一起读取到缓存池中,因为用户极大的可能性会读取它的相邻数据页,那flush的时候会不会也把相邻页给刷回磁盘呢?这样不就造成io的浪费了么?大量的io操作是无用功。


是的innodb是会将相邻的缓存页一起flush到磁盘的,我们可以通过innodb_flush_neighbors设置 禁止flush相邻页到磁盘,减少与磁盘的io次数与时间,0是禁止 我们设置innodb_flush_neighbors=0。


最后一个就是设置mysql中的线程池了,一般情况下设置成机器核数即可,我们设置的是thread_pool_size=48


以上这些配置改完后重启mysql即可


$ /home/lv/mysql/bin/mysqladmin  -u root -P8901 -p'root123' shutdown
$ /home/lv/mysql/bin/mysqld_safe --defaults-file=/home/lv/mysql/etc/mysql_8901.cnf &

3,压测优化后的数据库

我们调优完后 通过sysbench 进行压测。这里不在介绍sysbench的安装了,直接看下压测条件和命令


只读模式:

            20张表 每张表500w的数据量,60个线程并发读取,持续5分钟

$ sysbench --db-driver=mysql --time=300 --threads=60 --report-interval=1 --mysql-host=192.168.1.108 --mysql-port=8901 --mysql-user='root' --mysql-password='root123' --mysql-db=lv--tables=20 --table-size=5000000 oltp_read_only --db-ps-mode=disable run


我去,纯读模式下qps居然可以达到30w



网卡直接干到了6.4 Gb/s,cpu 也几乎快打满了



读写混合的情况下,qps达到8w 

sysbench --db-driver=mysql --time=300 --threads=60 --report-interval=1 --mysql-host=192.168.1.108 --mysql-port=8901 --mysql-user='lv' --mysql-password='root123' --mysql-db=gang --tables=20 --table-size=5000000 oltp_read_write --db-ps-mode=disable run


就是这么简单的几个参数,让msyql性能提升了几个数量级,大家有时间了也尝试下吧。


其实总的功劳要归功于buffer_pool,mysql的crud具体是在buffer_pool中怎么操作的呢?大家可以想一想,咱们下期在细说 mysql中的buffer_pool。