MySQL磁盘IO设置问题

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
云数据库 RDS PostgreSQL,高可用系列 2核4GB
简介:

下面的部分内容来自《深入浅出MySQL》、老叶的视频、网上其他人的blog。


这里列出的是MySQL的一些非运行参数的优化部分,具体如下:

(对于使用云主机的用户,下文中的部分优化方法是无法奏效的)

0、使用SSD。资金不足的话,使用RAID设备 【建议使用RAID10,因为RAID5的性能并不太高】

可以SSD+SAS混合使用。SSD存放数据文件。mysql的日志文件还是存在普通机械磁盘上,因为这些日志本来就是顺序IO的,存在SSD上浪费磁盘。


1、RAID卡设置

关闭读cache:RAID卡上的cache容量有限,我们选择direct方式读取数据,从而忽略读cache。

关闭预读:RAID卡的预读功能对于随机IO几乎没有任何提升,所以将预读功能关闭。

关闭磁盘cache:一般情况下,如果使用RAID,系统会默认关闭磁盘的cache,也可以用命令强制关闭。

以上设置都可以通过RAID卡的命令行来完成,比如LSI芯片的RAID卡使用megacli命令。



2、禁止操作系统更新文件的atime属性

# vim /etc/fstab,将mysql数据文件存放的分区加上noatime挂载属性即可,类似如下:

UUID=ccbb4c85-32ff-4b8d-ae58-f39569b67d96 /data   ext4  defaults,noatime  1 2

# mount -o remount,noatime /data

# 查看设备UUID的命令: blkid /dev/sdb1  


3、使用裸设备存放InnoDB的共享表空间 (目前很少这么用了,直接用SSD)

vim my.cnf如下:

[mysqld]

innodb_data_home_dir=

innodb_data_file_path=/dev/hdd1:3Gnewraw;/dev/hdd2:2Gnewraw


然后启动MySQL服务,让其自动完成分区的初始化,然后关闭MySQL。此时还不能创建或修改InnoDB表。


将my.cnf的文件继续修改下:

[mysqld]

innodb_data_home_dir=

innodb_data_file_path=/dev/hdd1:3Graw;/dev/hdd2:2Graw


然后重启MySQL服务,即可使用。



4、关注RAID卡的BBWC (Battery Backed Write Cache 电池充放电)问题

RAID卡上自带的电池会定期的充放电以进行电池校准。

每次充放电时间差不多3小时,期间RAID卡从数据安全角度考虑会自动禁用write back改为Write Through策略,这样的话系统IO性能会出现较大的波动。这很大几率会影响到MySQL的性能。


可以使用MegaCli64来查看和设置RAID卡缓存策略。如下:

# MegaCli64 -LDInfo -Lall -aALL 可以看到CurrentCache Policy 即当前的缓存策略。

我们可以临时修改RAID卡策略,在电池充放电期间强制使用Write Cache OK if Bad BBU策略,等充放电完成后,再将其恢复成No Write Cache if Bad BBU,避免断电可能导致的数据丢失。


另外,我们可以在业务低谷时候形象充放电操作,避免在业务高峰发生RAID卡充放电的执行。我们可以从BBU电池的日志中找到下次电池reclean的时间:

# MegaCli64 -fwtermlog -dsply -a0 -nolog

或# MegaCli64 -AdpBbuCmd -GetBbuProperties -aall


也可以手动触发电池的reclean操作:MegaCli64 -AdpBbuCmd -BbuLearn -aAll




5、调整磁盘IO调度算法

IO请求合并能减少磁盘寻道的次数。对于相邻山区的访问通过合并处理,对于非相邻扇区的访问则通过排序处理。

Linux下实现了4种IO调度算法。NOOP、最后期限算法Deadline、完全公平队列算法CFQ、预期算法Anticipatory

2.6.17内核版本以后,系统默认是CFQ算法。

根据理论(这里略过,需要了解的看《深入浅出MySQL》Page371),有如下结论:

1、在完全随机的访问环境下,CFQ和Deadline性能差异很小,但是在有大的连续IO出现的情况下,CFQ可能会造成小IO的响应延时增加,所以建议MySQL服务器设置为Deadline。

2、对于SSD设备,采用NOOP或Deadline通常可能获取到比默认更好的性能。


修改磁盘IO调度算法的方法: 

# dmesg|grep -i scheduler   查看到系统支持的IO调度算法【默认是noop anticipatory deadline [cfq]】

# more /sys/block/sda/queue/scheduler  查看当前使用的调度算法

# echo 'deadline' > /sys/block/sda/queue/scheduler  修改后立即生效【临时生效】

# vim /etc/grub.conf 在kernel行的末尾添加elevator=deadline   重启即可永久生效



6、NUMA架构优化

常用服务器大体分为3类:

SMP  对称多处理器结构

NUMA  非一致性内存访问结构

MPP  海量并行处理结构

SMP主要的特征就是共享,系统中所有的资源资源都是共享的,导致SMP服务器的扩展能力非常有限。由于每个CPU都要通过相同的总线访问相同的内存资源,如果两个CPU同时请求访问同一个内存资源(如同一段内存地址),就会产生资源争用的问题。CPU越多这种情况出现的概率就越大。


NUMA把一台计算机分成多个节点Nodes,每个节点内部拥有多个CPU,节点内部使用共有的内存控制器,节点之间是通过互联模块进行连接和信息交互。节点的所有内存对于本节点所有的CPU都是等同的,而对于其他节点中的所有CPU都是不同的。每个CPU可以访问整个系统内存,但是访问本地节点的内存较快,访问非本地节点的内存较慢(要经过互联模块),即CPU访问内存的速度和节点的距离有关,距离称为Node Distance。


[root@posp-linux ~]# numactl --hardware

available: 2 nodes (0-1)

node 0 cpus: 0 1 2 3 4 5 12 13 14 15 16 17

node 0 size: 16349 MB

node 0 free: 2654 MB

node 1 cpus: 6 7 8 9 10 11 18 19 20 21 22 23

node 1 size: 16383 MB

node 1 free: 6079 MB

node distances:

node   0   1 

  0:  10  20 

  1:  20  10 

[root@posp-linux ~]# free -m

             total       used       free     shared    buffers     cached

Mem:         32068      23335       8733          1        679      18982

-/+ buffers/cache:       3673      28395

Swap:        12137         88      12049


上图可以看到有2个node,每个node的内存为16GB。上面的node distance中节点本地内存声明距离为10,非本地节点内存声明距离为20。


NUMA的内存分配策略有4种:

缺省 default  总是在本地节点分配(分配在当前进程运行的节点上)

绑定 bind     强制分配到指定节点上

交叉 interleave 在所有节点或指定节点上交叉分配内存

优先 preferred  在指定节点上分配,失败则在其他节点上分配


[root@posp-linux ~]# numactl --show  显示当前系统的NUMA策略

policy: default

preferred node: current

physcpubind: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 

cpubind: 0 1 

nodebind: 0 1 

membind: 0 1


默认的default策略是优先在进程所在CPU的本地内存中分配,会导致CPU节点之间内存分配不均衡,当某个CPU节点内存不足时,会导致swap产生,而不是从远程节点分配内存,这就是swap insanity现象。


MySQL是单进程多线程的架构。当NUMA采用默认default的分配策略时,MySQL进程会被并且仅被分配到NUMA的一个节点上去。假设MySQL配置的14G内存超过了这个节点的本地8G内存,这种情况下Linux宁愿使用Swap也不会去瓜分其他节点的物理内存。这就导致一个问题:虽然free -m看上去还有内存可用,但是实际上MySQL进程已经开始使用到Swap了。


MySQL对NUMA的支持不太好,如果单机只运行的MySQL的话,建议关闭NUMA。方法如下:

# vim /etc/grub.conf 在kernel最后加上numa=off

保存后,重启服务器即可。

关闭后,类似下面的样子:

[root@node1 ~]# numactl --show

policy: default

preferred node: current

physcpubind: 0 1 2 3 

cpubind: 0 

nodebind: 0 

membind: 0


或者通过numactl修改NUMA分配策略为interleave也行!!!


如果单机运行多个MySQL实例,我们可以将MySQL绑定在不同的CPU节点上,并且采用绑定的内存分配策略,强制在本节点内分配内存,这样既可以充分利用硬件的NUMA特性,又避免了单实例MySQL对多核CPU利用率不高的问题。



7、文件系统设置

挂载时候可以不记录时间:

defaults,noatime,nodiratime 


补充:挂载时候使用 noatime,nodiratime 选项的问题

未指定"noatime,nodiratime"的情况下:

read文件的时候会导致atime更新,不会导致mtime和ctime更新

write文件只会导致mtime和ctime更新,不会导致atime更新。


说明:当以noatime选项加载(mount)文件系统时,对文件的读取不会更新文件属性中的atime信息。设置noatime的重要性是消除了文件系统对文件的写操作,文件只是简单地被系统读取。



在平日里经常有删除文件的需求,大概如下:

删除过去N天内都未访问过的文件或者目录(删除N天前访问过的文件)


    # 注意这条命令很危险! 

#  find /home/fire/ -atime +N -exec rm -rf {} \;

假设 /home/fire 目录是一周之前创建的,那么对于这条命令有两个执行结果:


# find /home/fire/ -atime +7 -exec rm -rf {} \;

指定"noatime":find的时候发现 /home/fire 是7天之前创建的,立马就会删除整个目录。而且还会报错"find: /home/fire: No such file or directory",原因就是第一个rm -rf /home/fire 之后 find失败了。这种是很危险的!原因是会误删除文件。

未指定"noatime":那就得看情况,如果/home/fire过去7天没有被访问过,那么就和情况一一样,直接删除。

如果过去7天内,该目录有人访问过,atime肯定是7天之内,那么就会遍历下面的目录,依次按照之前逻辑。但是遍历过程会更改目录的atime。

看了上面的例子会发现find去删除目录的时候变得好复杂,而且一定要小心。所以find删除更适用于删除文件,不要删除目录。


启用noatime的时候,删除N天内未被访问过的文件的方法:

#  find /home/fire/ -atime +N -type f -exec rm -f {} \;










本文转自 lirulei90 51CTO博客,原文链接:http://blog.51cto.com/lee90/1971324,如需转载请自行联系原作者
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
3月前
|
NoSQL 关系型数据库 MySQL
在Visual Studio Code中设置MySQL源码调试环境
以上步骤涵盖了在VS Code中设置MySQL源码调试环境的主要过程,是一个相对高级的任务,旨在为希望建立强大开发和调试环境的开发者提供指引。遵循这些步骤,将可以利用VS Code强大的编辑和调试功能来深入理解和改进MySQL数据库的底层实现。
332 0
|
6月前
|
Java 关系型数据库 MySQL
在Linux操作系统上设置JDK、Tomcat、MySQL以及J2EE后端接口的部署步骤
让我们总结一下,给你的Linux操作系统装备上最强的军队,需要先后装备好JDK的弓箭,布置好Tomcat的阵地,再把MySQL的物资原料准备好,最后部署好J2EE攻城车,那就准备好进军吧,你的Linux军团,无人可挡!
155 18
|
9月前
|
关系型数据库 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 崩溃时有丢失数据风险。
228 3
|
9月前
|
存储 关系型数据库 MySQL
MySQL进阶突击系列(09)数据磁盘存储模型 | 一行数据怎么存?
文中详细介绍了MySQL数据库中一行数据在磁盘上的存储机制,包括表空间、段、区、页和行的具体结构,以及如何设计和优化行数据存储以提高性能。
|
10月前
|
关系型数据库 MySQL Docker
docker pull mysql:8.0.26提示Error response from daemon: Get “https://registry-1.docker.io/v2/“: EOF错误
docker pull mysql:8.0.26提示Error response from daemon: Get “https://registry-1.docker.io/v2/“: EOF错误
3459 9
|
11月前
|
关系型数据库 MySQL Linux
升级到MySQL 8.4,MySQL启动报错:io_setup() failed with EAGAIN
当MySQL 8.4启动时报错“io_setup() failed with EAGAIN”时,通常是由于系统AIO资源不足所致。通过增加AIO上下文数量、调整MySQL配置、优化系统资源或升级内核版本,可以有效解决这一问题。上述解决方案详细且实用,能够帮助管理员快速定位并处理此类问题,确保数据库系统的正常运行。
384 9
|
11月前
|
SQL
南大通用GBase 8a配置gcware日志等级,减少日志输出,节省磁盘IO
南大通用GBase 8a配置gcware日志等级,减少日志输出,节省磁盘IO
|
存储 缓存 Java
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
这篇文章详细介绍了Java中的IO流,包括字符与字节的概念、编码格式、File类的使用、IO流的分类和原理,以及通过代码示例展示了各种流的应用,如节点流、处理流、缓存流、转换流、对象流和随机访问文件流。同时,还探讨了IDEA中设置项目编码格式的方法,以及如何处理序列化和反序列化问题。
352 1
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
|
12月前
|
关系型数据库 MySQL 数据库
MySQL事务隔离级别及默认隔离级别的设置
在数据库系统中,事务隔离级别是一个关键的概念,它决定了事务在并发执行时如何相互隔离。MySQL提供了四种事务隔离级别,每种级别都解决了不同的并发问题。本文将详细介绍这些隔离级别以及MySQL的默认隔离级别。
|
关系型数据库 MySQL Linux
Linux系统如何设置自启动服务在MySQL数据库启动后执行?
【10月更文挑战第25天】Linux系统如何设置自启动服务在MySQL数据库启动后执行?
681 3