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

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
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"就是最多可以拥有的子进程数量;

 

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
22天前
|
自然语言处理 搜索推荐 关系型数据库
MySQL实现文档全文搜索,分词匹配多段落重排展示,知识库搜索原理分享
本文介绍了在文档管理系统中实现高效全文搜索的方案。为解决原有ES搜索引擎私有化部署复杂、运维成本高的问题,我们转而使用MySQL实现搜索功能。通过对用户输入预处理、数据库模糊匹配、结果分段与关键字标红等步骤,实现了精准且高效的搜索效果。目前方案适用于中小企业,未来将根据需求优化并可能重新引入专业搜索引擎以提升性能。
|
1月前
|
缓存 算法 关系型数据库
MySQL底层概述—8.JOIN排序索引优化
本文主要介绍了MySQL中几种关键的优化技术和概念,包括Join算法原理、IN和EXISTS函数的使用场景、索引排序与额外排序(Using filesort)的区别及优化方法、以及单表和多表查询的索引优化策略。
104 22
MySQL底层概述—8.JOIN排序索引优化
|
1月前
|
关系型数据库 MySQL 数据库
RDS用多了,你还知道MySQL主从复制底层原理和实现方案吗?
随着数据量增长和业务扩展,单个数据库难以满足需求,需调整为集群模式以实现负载均衡和读写分离。MySQL主从复制是常见的高可用架构,通过binlog日志同步数据,确保主从数据一致性。本文详细介绍MySQL主从复制原理及配置步骤,包括一主二从集群的搭建过程,帮助读者实现稳定可靠的数据库高可用架构。
98 9
RDS用多了,你还知道MySQL主从复制底层原理和实现方案吗?
|
1月前
|
SQL 关系型数据库 MySQL
MySQL底层概述—7.优化原则及慢查询
本文主要介绍了:Explain概述、Explain详解、索引优化数据准备、索引优化原则详解、慢查询设置与测试、慢查询SQL优化思路
123 15
MySQL底层概述—7.优化原则及慢查询
|
1月前
|
存储 关系型数据库 MySQL
MySQL底层概述—6.索引原理
本文详细回顾了:索引原理、二叉查找树、平衡二叉树(AVL树)、红黑树、B-Tree、B+Tree、Hash索引、聚簇索引与非聚簇索引。
MySQL底层概述—6.索引原理
|
25天前
|
SQL 关系型数据库 MySQL
基于SQL Server / MySQL进行百万条数据过滤优化方案
对百万级别数据进行高效过滤查询,需要综合使用索引、查询优化、表分区、统计信息和视图等技术手段。通过合理的数据库设计和查询优化,可以显著提升查询性能,确保系统的高效稳定运行。
46 9
|
1月前
|
监控 关系型数据库 MySQL
MySQL和SQLSugar百万条数据查询分页优化
在面对百万条数据的查询时,优化MySQL和SQLSugar的分页性能是非常重要的。通过合理使用索引、调整查询语句、使用缓存以及采用高效的分页策略,可以显著提高查询效率。本文介绍的技巧和方法,可以为开发人员在数据处理和查询优化中提供有效的指导,提升系统的性能和用户体验。掌握这些技巧后,您可以在处理海量数据时更加游刃有余。
94 9
|
1月前
|
关系型数据库 MySQL
图解MySQL【日志】——磁盘 I/O 次数过高时优化的办法
当 MySQL 磁盘 I/O 次数过高时,可通过调整参数优化。控制刷盘时机以降低频率:组提交参数 `binlog_group_commit_sync_delay` 和 `binlog_group_commit_sync_no_delay_count` 调整等待时间和事务数量;`sync_binlog=N` 设置 write 和 fsync 频率,`innodb_flush_log_at_trx_commit=2` 使提交时只写入 Redo Log 文件,由 OS 择机持久化,但两者在 OS 崩溃时有丢失数据风险。
48 3
|
1月前
|
SQL 关系型数据库 MySQL
数据库数据恢复——MySQL简介和数据恢复案例
MySQL数据库数据恢复环境&故障: 本地服务器,安装的windows server操作系统。 操作系统上部署MySQL单实例,引擎类型为innodb,表空间类型为独立表空间。该MySQL数据库没有备份,未开启binlog。 人为误操作,在用Delete命令删除数据时未添加where子句进行筛选导致全表数据被删除,删除后未对该表进行任何操作。
|
5天前
|
关系型数据库 MySQL 数据库连接
docker拉取MySQL后数据库连接失败解决方案
通过以上方法,可以解决Docker中拉取MySQL镜像后数据库连接失败的常见问题。关键步骤包括确保容器正确启动、配置正确的环境变量、合理设置网络和权限,以及检查主机防火墙设置等。通过逐步排查,可以快速定位并解决连接问题,确保MySQL服务的正常使用。
108 82

相关产品

  • 云数据库 RDS MySQL 版
  • 推荐镜像

    更多