怎么判断mysql读和写达到了瓶颈

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎么判断mysql读和写达到了瓶颈相关的知识,希望对你有一定的参考价值。

1. mysql处在高负载环境下,磁盘IO读写过多,肯定会占用很多资源,必然会CPU占用过高,所以可以用top命令查看MySQL所在服务器的cpu使用情况,从而分析是否有瓶颈;
2. show processlist查看MySQL当前的执行状态,查看是否有大量的Sleep或Locked状态;
参考技术A

通过sysbench的oltp_read_write测试来模拟业务压力、以此来给指定的硬件环境配置一份比较合理的MySQL配置文件。


环境介绍

硬件配置


请点击输入图片描述

软件环境


请点击输入图片描述


优化层级与指导思想

优化层级

MySQL数据库优化可以在多个不同的层级进行,常见的有:

    SQL优化

    参数优化 

    架构优化

    本文重点关注:参数优化

    指导思想

    日志先行 -- 一个事务能否成功提交的关键是日志是否成功落盘,与数据没有太大的关系;也就是说对写的优化可以表述为各方面的资源向写操作倾斜。

    瓶颈分析 -- 通过show global status 的各个计数器的值基本上就能分析出当前瓶颈所在,再结合一些简单的系统层面的监控工具如top iostat 就能明确瓶颈。

    整体性能是“读”&“写”之间的再平衡。

有名管道的读和写

管道(pipe)是一种文件,可以调用read,write,close等操作文件的接口来操作管道;管道还属于一种独特的文件系统pipefs,其本质是内核维护了一块缓冲区与管道文件相关联,所有对管道文件的操作,都会被内核转换为对这块缓冲区内存的操作.

#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
	int fd[2];
	int result = pipe(fd);
	if(result != 0)
	{
		printf("create pipe failed, app exit!\\n");
		exit(-1);
	}	
	printf("create pipe succeed!\\n");
	printf("pipefd[0] : %d, pipefd[1] : %d\\n");
	printf("close pipe!\\n");
	close(fd);
	return 0;
}

创建管道成功后,系统会返回2个已经打开的文件描述符,其中pipefd[0]可以读(调用read函数),pipefd[1]可以写(调用write函数).
而此时系统创建的管道是无名的,也就是说这个管道是没有名字的,无法被外部的进程(没有血缘关系)所访问(写入).
mkfifo函数可以创建一个有名称的管道.该函数创建好的fifo文件就可以运用到不同进程间的通信了.

/* 读取管道中的数据 mkfifo_read.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

#define FIFONAME "/tmp/mkfifo.0001"

int main(int argc,char *argv[])
{
	int result;
	int fd_read;
	char buf_read[1024];
	result = mkfifo(FIFONAME, O_CREAT|O_EXCL|0666);
	if(result < 0)
	{
		printf("mkfifo failed, app exit!\\n");
		exit(-1);
	}
	printf("mkfifo succeed, fifo\'s name : %s\\n", FIFONAME);

	memset(buf_read, \'\\0\', sizeof(buf_read));
	fd_read = open(FIFONAME, O_RDONLY|O_NONBLOCK, 0);
	if(fd_read < 0)
	{
		printf("open [%s] failed, app exit!\\n", FIFONAME);
		exit(-1);
	}
	printf("open [%s] succeed!\\n", FIFONAME);
	while(1)
	{
		if(read(fd_read, buf_read, sizeof(buf_read)) < 0)
		{
			printf("no data ...\\n");
		}
		if(buf_read[0] != \'\\0\') /* 表示读取到了数据 */
			printf("read data : %s\\n", buf_read);
		sleep(1);
		memset(buf_read, \'\\0\', sizeof(buf_read)); /* 重新初始化 */
	}
	close(fd_read);
	return 0;
}
/* 向管道中写入数据 mkfifo_write.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

#define FIFONAME "/tmp/mkfifo.0001"

int main(int argc,char *argv[])
{
	int result;
	int count = 0;
	int fd_write;
	char buf_write[1024];
	memset(buf_write, \'\\0\', sizeof(buf_write));
	fd_write = open(FIFONAME, O_RDWR|O_NONBLOCK, 0);
	if(fd_write < 0)
	{
		printf("open fifo failed, app exit!\\n");
		exit(-1);
	}
	printf("open fifo [%s] succeed!\\n", FIFONAME);
	while(1)
	{
		if(fgets(buf_write, sizeof(buf_write), stdin) == NULL)
		{	
			printf("get data from [stdin] failed, app exit!\\n");
			break;
		}

		if(strncmp("EXIT", buf_write, sizeof("EXIT") - 1) == 0)
		{
			printf("catch [EXIT] command, app exit!\\n");
			break;
		}
		printf("[%d] : write data : %s\\n", count, buf_write);
		result = write(fd_write, buf_write, sizeof(buf_write));
		if(resul < 0)
		{
			printf("[%d] : write data failed, app exit!\\n", count);
			break;
		}
		memset(buf_write, \'\\0\', sizeof(buf_write));
		count++;
	}
	
	printf("close fd_write : %d\\n", fd_write);
	close(fd_write);
	return 0;
}

运行截图

 

以上是关于怎么判断mysql读和写达到了瓶颈的主要内容,如果未能解决你的问题,请参考以下文章

docker搭建mysql读写分离

如何判断MSSQL数据库磁盘出现了瓶颈

如果sql语句已经达到优化,瓶颈在于数据文件的磁盘io,此时可以怎么调整

MySQL:常用分库分表方案汇总

常用 MySQL 分库分表方案

MySQL的分库分表方案汇总