MYSQl深入探索系列四 服务端优化
目录
环境准备
常见innodb存储引擎常见参数及调优
压测优化后的数据库
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=apps
report-host=192.168.1.108
report-port=8901
server-id=1088901 命名规则:机器ip后两个+端口
port=8901
socket=/tmp/mysql_8901.sock
datadir = /data1/apps/lv/mysql_data_8901/data/data
basedir = /data1/apps/lv/mysql_exec_8901
secure_file_priv = /data1/apps/lv/mysql_data_8901/data/data
log_error = /data1/apps/lv/mysql_data_8901/data/logs/error.log
slow_query_log_file=/data1/apps/lv/mysql_data_8901/data/logs/slow.log
log_bin = /data1/apps/lv/mysql_data_8901/data/binlog/mysql-bin.log
relay_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
登陆成功后执行:
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即可
'root123' shutdown /home/lv/mysql/bin/mysqladmin -u root -P8901 -p
$ /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。