MySQL原理简介—6.简单的生产优化案例

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介: 本文介绍了数据库和存储系统的几个主题:1. **MySQL日志的顺序写和数据文件的随机读指标**:解释了磁盘随机读和顺序写的原理及对数据库性能的影响。2. **Linux存储系统软件层原理及IO调度优化原理**:解析了Linux存储系统的分层架构,包括VFS、Page Cache、IO调度等,并推荐使用deadline算法优化IO调度。3. **数据库服务器使用的RAID存储架构**:介绍了RAID技术的基本概念及其如何通过多磁盘阵列提高存储容量和数据冗余性。4. **数据库Too many connections故障定位**:分析了MySQL连接数限制问题的原因及解决方法。

大纲

1.MySQL日志的顺序写和数据文件的随机读指标

2.Linux存储系统软件层原理及IO调度优化原理

3.数据库服务器使用的RAID存储架构介绍

4.数据库Too many connections故障定位

 

1.MySQL日志的顺序写和数据文件的随机读指标

(1)磁盘随机读操作

(2)磁盘顺序写操作

 

(1)磁盘随机读操作

MySQL在执行增删改查时,会从表空间的磁盘文件里,读取数据页出来。这个过程是典型的磁盘随机读操作。

 

下图有一个磁盘文件,里面有很多数据页。可能要在一个随机位置读取一个数据页到缓存,这就是磁盘随机读。因为要读取的这个数据页可能在磁盘的任意一个位置,所以读取磁盘里的数据页时只能使用随机读的这种方式。

磁盘随机读的性能是比较差的,不可能每次更新数据都进行磁盘随机读。必须是读取一个数据页之后放到Buffer Pool的缓存里,下次要更新时就可以直接更新Buffer Pool里的缓存页。

 

对于磁盘随机读来说,主要关注的性能指标是IOPS和响应延迟latency。

 

一.影响磁盘随机读的IOPS

这个IOPS,就是指底层存储系统每秒可以执行多少次磁盘随机读写操作。比如每秒执行1000个还是200个磁盘随机读写操作,很影响数据库性能。IOPS指标对数据库的增删改查操作的QPS影响非常大,某种程度上决定了MySQL每秒能执行多少条SQL语句。底层存储的IOPS越高,数据库的并发能力就越强。

 

二.影响磁盘随机读的响应延迟latency

磁盘随机读写操作的响应延迟,指的是执行一次读写操作耗费多少时间。磁盘随机读写操作的响应延迟,也对数据库性能影响很大。假设底层磁盘支持每秒执行200个随机读写操作,但是每个读写操作耗费10ms完成和耗费1ms完成,差别是很大的。所以响应延迟,决定了MySQL执行单个增删改查SQL语句的性能。

 

所以对于核心业务的数据库的生产环境机器规划,一般推荐用SSD固态硬盘,而不是机械硬盘。因为固态硬盘的随机读写并发能力和响应延迟都比机械硬盘好得多,可以大幅提升数据库的QPS和性能。

 

(2)磁盘顺序写操作

已经知道,当Buffer Pool的缓存页更新了数据后,必须要写一条redo日志,这个redo日志就是用了顺序写。

 

所谓磁盘顺序写,就是指在一个磁盘日志文件里,一直在末尾追加日志。磁盘顺序写的性能其实是很高的,几乎可以跟内存随机读写的性能差不多。尤其是在数据库里其实也用到了OS Cache机制:比如将redo log顺序写入磁盘前,会先进入OS Cache操作系统内存缓存里。

 

对于磁盘顺序写来说,主要关注的是磁盘每秒读写数据量的吞吐量指标。

 

比如每秒可以写入磁盘100MB和每秒可以写入磁盘200MB数据,这对数据库的并发能力影响也是很大的。因为每一次更新数据,都必然涉及多个磁盘随机读取数据页的操作,也会涉及一条redo日志的磁盘顺序写操作。当然磁盘日志文件的顺序读写操作的响应延迟,也决定了数据库的性能。写redo日志文件越快,SQL语句性能就越高。

 

所以磁盘读写的IOPS指标,即每秒可以执行多少个随机读写操作,以及每秒读写磁盘数据量的吞吐量指标,即每秒可写入多少redo日志,整体决定了数据库的并发能力。而磁盘随机读写操作的响应延迟和顺序读写操作的响应延迟,整体决定了数据库执行SQL语句的性能。

 

2.Linux存储系统软件层原理及IO调度优化原理

Linux的存储系统分为:VFS层、文件系统层、Page Cache缓存层、通用Block层、IO调度层、Block设备驱动层、Block设备层。

步骤一:

当MySQL发起一次数据页的随机读写或redo日志文件的顺序读写时,会把磁盘IO请求交给Linux的VFS层。VFS层的作用,就是根据用户要对哪个目录中的文件执行的磁盘IO操作,把IO请求交给具体的文件系统。比如在Linux中,有的目录里的文件是由NFS文件系统管理的,有的目录里的文件是由Ext3文件系统管理的。这时VFS层需要根据用户对哪个目录下的文件发起的读写IO请求,把请求转交给对应的文件系统。

 

步骤二:

接着文件系统会先在Page Cache这个基于内存的页缓存里,查找是否有用户需要的数据。如果有就直接基于内存页缓存来执行读写,如果没有就继续往下执行。即把请求交给通用Block层,把用户对文件的IO请求转换为Block IO请求。

 

步骤三:

IO请求转换为Block IO请求后,会把这个Block IO请求交给IO调度层。在IO调度层这一层里默认使用CFQ公平调度算法。

 

这个算法的意思是,假如数据库收到了多条SQL语句同时在执行IO操作,有一条SQL语句"update where id = 1"只需更新磁盘上的一个数据即可,有另外一条SQL语句"select *"可能需要IO读取磁盘上的大量数据。那么根据CFQ公平调度算法,会导致数据库先执行第二条SQL读取大量数据的IO操作,可能耗时较久。而第一个仅更新少量数据的SQL的IO操作,就一直在等待,得不到执行。

 

所以生产环境一般建议调整IO调度层的调度算法为deadline IO调度算法。该算法的核心思想是,任何一个IO操作都不能一直不停的等待,在指定的时间范围内,都必须让IO操作去执行。

 

基于deadline IO调度算法,上面第一条SQL语句的更新少量数据的IO操作可能在等待一会后,就可以得到执行机会了,这也是一个生产环境的IO调度优化经验。

 

步骤四:

当IO完成调度后,就会决定哪个IO请求先执行,哪个IO请求后执行。此时可以执行的IO请求就会交给Block设备驱动层。这一层又会经过驱动把IO请求发送给真正的存储硬件,即Block设备层。

 

步骤五:

最后硬件设备完成IO读写操作后,会把结果沿着进来的层次依次返回。最终MySQL就可以得到本次IO读写操作的结果。这也就是MySQL和Linux存储系统交互的原理。

 

3.数据库服务器使用的RAID存储架构介绍

一般很多数据库部署在机器上时,存储都是搭建RAID存储架构。RAID就是一个磁盘冗余阵列;

 

磁盘冗余阵列的解释是:假设服务器里的磁盘就一块,一旦磁盘容量不够,可以多加几块磁盘。但机器里有多块磁盘后,怎么进行管理,及怎么在多块磁盘上存放数据?所以针对该问题,在存储层面会往机器加多块磁盘,然后引入RAID技术。因此可以理解为RAID就是用来管理机器里多块磁盘的一种磁盘阵列技术。有了RAID之后,服务器在往磁盘里读写数据时,RAID就会告诉服务器应该往哪块磁盘上读写数据。

有了RAID这种多磁盘阵列技术后,就可以在一台服务器里加多块磁盘,扩大服务器的磁盘存储空间了。当需要往磁盘里写数据时,通过RAID技术可以帮助选择一块磁盘写入。当需要从磁盘读取数据时,通过RAID技术也知道从哪块磁盘去读取。此外,RAID技术很重要的一个作用就是它可以实现数据冗余机制。

 

所谓的数据冗余机制:就是如果往一块磁盘写入一批数据,但这块磁盘坏了,则数据就会丢失。而RAID磁盘冗余阵列技术,可以往两块磁盘上都写入同样的一份数据。这样可以让两块磁盘上的数据一样,作为冗余备份。即便当一块磁盘坏掉了,也可以从另外一块磁盘读取冗余数据出来。而这一切都是RAID技术自动帮忙管理的,所以RAID技术实际上就是管理多块磁盘的一种磁盘冗余阵列技术。

 

4.数据库Too many connections故障定位

数据库无法连接的问题,异常信息通常是:

ERROR 1040(HY000): Too many connections

这个异常说明数据库的连接池已经有太多的连接,不能再和客户端建立新的连接了。

 

通过数据库整体架构原理可知:数据库自己其实是有一个连接池的,每个Java系统服务实例也有一个连接池。Java系统的每个连接Socket都会对应数据库连接池里的一个连接Socket。当出现"Too many connections"时,说明它的连接池的连接已经满了,Java业务系统不能跟它建立更多的连接。

一.一个生产案例

数据库部署在64GB的大内存物理机上,机器配置各方面都很高。连接这台物理机的Java系统部署在2台机器上。Java系统设置的连接池最大是200,所以Java系统总共最多会和数据库建立400个连接。

 

但是这时数据库却报了Too many connections异常,说明当前数据库无法建立400个网络连接,这么高配置的数据库机器居然不能建立400个连接。

 

于是检查一下MySQL的配置文件my.cnf,里面有一个关键的参数max_connections。max_connections表示的是MySQL能建立的最多连接数,设置为800。

 

这就奇怪了,明明设置了MySQL最多可以建立800个连接,居然两台机器要建立400个连接都不行。

 

这时登录MySQL执行如下命令进行线上确认:

mysql> show varilables like 'max_connections';

显示的结果是:当前MySQL仅仅只是建立了214个连接而已。因此猜测,MySQL是根本不管my.cnf设置的max_connections,就直接强行把最大连接数设置为214了。于是可以去检查一下MySQL的启动日志,可以看到如下字样:

Could not increase number of max_open_files to more than mysqld (request:65535)
Changed limits: max_connections: 214 (requestd 2000)
Changed limits: table_open_cache: 400 (requestd 4096)

这表明MySQL发现自己无法设置max_connections为我们期望的800,只能强行限制为214了,而导致这种情况的原因就是,Linux操作系统把进程可以打开的文件句柄数限制为1024了,最终导致MySQL最大连接数是214。

 

(2)问题的解决

使用"ulimit -HSn"更改最大文件句柄数:

$ ulimit -HSn 65535

然后使用如下命令进行检查修改是否生效:

$ cat /etc/security/limits.conf
$ cat /etc/rc.local

如果都修改好后,在my.cnf里也确保max_connections参数调整好了,就可以重启服务器重启MySQL了,这样Linux的最大文件句柄就会生效,也就是让MySQL的最大连接数生效。

 

为何Linux的最大文件句柄限制为1024时,MySQL的最大连接数是214?

因为这是MySQL源码写死的,源码中有一个计算公式,算下来就是214。

 

Linux的ulimit命令的作用是什么?

Linux默认会限制每个进程对机器资源的使用:包括可打开的文件句柄数的限制、可打开的子进程数的限制、网络缓存的限制、最大可锁定的内存大小等。

 

Linux操作系统设计的初衷是:

尽量避免某个进程突然耗尽机器上的所有资源,所以才会默认进行限制。

 

对于我们来说常见的一个问题就是,文件句柄的限制。如果Linux限制一个进程的文件句柄太少的话,那么就会导致这个进程没法创建大量的网络连接,无法正常工作。

 

MySQL运行时就是Linux上的一个进程,当它需要跟很多业务系统建立大量连接时,如果限制最大文件句柄数量,就不能建立太多连接。

 

因此如果在生产环境部署一个系统,比如数据库系统、消息中间件系统、存储系统、缓存系统后,都需要调整一下Linux的一些内核参数,而这个文件句柄的数量是一定要调整的,通常都得设置为65535。还有比如Kafka之类的消息中间件,在生产环境部署时,如果不优化Linux内核参数,可能会导致Kafka无法创建足够的线程运行。

 

我们平时可以用ulimit命令来设置每个进程被限制使用的资源量,用ulimit -a就可以看到进程被限制使用的各种资源的量。

"core file size"代表进程崩溃时的转储文件的大小限制;
"max locked memory"就是最大锁定内存大小;
"open files"就是最大可以打开的文件句柄数量;
"max user processes"就是最多可以拥有的子进程数量;

 

相关文章
|
3天前
|
机器学习/深度学习 人工智能 自然语言处理
PAI Model Gallery 支持云上一键部署 DeepSeek-V3、DeepSeek-R1 系列模型
DeepSeek 系列模型以其卓越性能在全球范围内备受瞩目,多次评测中表现优异,性能接近甚至超越国际顶尖闭源模型(如OpenAI的GPT-4、Claude-3.5-Sonnet等)。企业用户和开发者可使用 PAI 平台一键部署 DeepSeek 系列模型,实现 DeepSeek 系列模型与现有业务的高效融合。
|
3天前
|
人工智能 搜索推荐 Docker
手把手教你使用 Ollama 和 LobeChat 快速本地部署 DeepSeek R1 模型,创建个性化 AI 助手
DeepSeek R1 + LobeChat + Ollama:快速本地部署模型,创建个性化 AI 助手
1698 96
手把手教你使用 Ollama 和 LobeChat 快速本地部署 DeepSeek R1 模型,创建个性化 AI 助手
|
1月前
|
供应链 监控 安全
对话|企业如何构建更完善的容器供应链安全防护体系
阿里云与企业共筑容器供应链安全
171370 16
|
10天前
|
Linux iOS开发 MacOS
deepseek部署的详细步骤和方法,基于Ollama获取顶级推理能力!
DeepSeek基于Ollama部署教程,助你免费获取顶级推理能力。首先访问ollama.com下载并安装适用于macOS、Linux或Windows的Ollama版本。运行Ollama后,在官网搜索“deepseek”,选择适合你电脑配置的模型大小(如1.5b、7b等)。通过终端命令(如ollama run deepseek-r1:1.5b)启动模型,等待下载完成即可开始使用。退出模型时输入/bye。详细步骤如下图所示,轻松打造你的最强大脑。
7866 85
|
1月前
|
供应链 监控 安全
对话|企业如何构建更完善的容器供应链安全防护体系
随着云计算和DevOps的兴起,容器技术和自动化在软件开发中扮演着愈发重要的角色,但也带来了新的安全挑战。阿里云针对这些挑战,组织了一场关于云上安全的深度访谈,邀请了内部专家穆寰、匡大虎和黄竹刚,深入探讨了容器安全与软件供应链安全的关系,分析了当前的安全隐患及应对策略,并介绍了阿里云提供的安全解决方案,包括容器镜像服务ACR、容器服务ACK、网格服务ASM等,旨在帮助企业构建涵盖整个软件开发生命周期的安全防护体系。通过加强基础设施安全性、技术创新以及倡导协同安全理念,阿里云致力于与客户共同建设更加安全可靠的软件供应链环境。
150306 32
|
18小时前
|
人工智能 自然语言处理 JavaScript
宜搭上新,DeepSeek 插件来了!
钉钉宜搭近日上线了DeepSeek插件,无需编写复杂代码,普通用户也能轻松调用强大的AI大模型能力。安装后,平台新增「AI生成」组件,支持创意内容生成、JS代码编译、工作汇报等场景,大幅提升工作效率。快来体验这一高效智能的办公方式吧!
725 4
|
2天前
|
API 开发工具 Python
阿里云PAI部署DeepSeek及调用
本文介绍如何在阿里云PAI EAS上部署DeepSeek模型,涵盖7B模型的部署、SDK和API调用。7B模型只需一张A10显卡,部署时间约10分钟。文章详细展示了模型信息查看、在线调试及通过OpenAI SDK和Python Requests进行调用的步骤,并附有测试结果和参考文档链接。
556 4
阿里云PAI部署DeepSeek及调用
|
10天前
|
人工智能 自然语言处理 Java
Spring AI,搭建个人AI助手
本期主要是实操性内容,聊聊AI大模型,并使用Spring AI搭建属于自己的AI助手、知识库。本期所需的演示源码笔者托管在Gitee上(https://gitee.com/catoncloud/spring-ai-demo),读者朋友可自行查阅。
927 41
Spring AI,搭建个人AI助手
|
3天前
|
机器学习/深度学习 人工智能 并行计算
一文了解火爆的DeepSeek R1 | AIGC
DeepSeek R1是由DeepSeek公司推出的一款基于强化学习的开源推理模型,无需依赖监督微调或人工标注数据。它在数学、代码和自然语言推理任务上表现出色,具备低成本、高效率和多语言支持等优势,广泛应用于教育辅导、金融分析等领域。DeepSeek R1通过长链推理、多语言支持和高效部署等功能,显著提升了复杂任务的推理准确性,并且其创新的群体相对策略优化(GRPO)算法进一步提高了训练效率和稳定性。此外,DeepSeek R1的成本低至OpenAI同类产品的3%左右,为用户提供了更高的性价比。
720 10
|
2月前
|
弹性计算 人工智能 安全
对话 | ECS如何构筑企业上云的第一道安全防线
随着中小企业加速上云,数据泄露、网络攻击等安全威胁日益严重。阿里云推出深度访谈栏目,汇聚产品技术专家,探讨云上安全问题及应对策略。首期节目聚焦ECS安全性,提出三道防线:数据安全、网络安全和身份认证与权限管理,确保用户在云端的数据主权和业务稳定。此外,阿里云还推出了“ECS 99套餐”,以高性价比提供全面的安全保障,帮助中小企业安全上云。
201992 15
对话 | ECS如何构筑企业上云的第一道安全防线