一、硬件层优化
1.1 CPU优化
# BIOS设置
- 电源管理:Performance Per Watt Optimized(DAPC) # 发挥CPU最大性能
- C-states/C1E:关闭 # 禁用CPU节能状态
- Turbo Boost:开启 # 保持全核睿频状态
1.2 内存优化
# BIOS设置
- Memory Frequency:Maximum Performance # 内存频率设为最佳性能
- Node Interleaving:启用 # 避免NUMA问题
1.3 NUMA说明
NUMA(Non-Uniform Memory Access)是非一致性内存访问架构,启用Node Interleaving可以让CPU交替访问内存,避免内存访问不均导致的性能问题。
二、磁盘I/O优化
2.1 硬件选型
| 优化项 | 推荐配置 | 说明 |
|---|---|---|
| 磁盘类型 | SSD | 比机械硬盘IOPS提升数百甚至万倍 |
| 阵列卡 | 配备CACHE+BBU | 大幅提升IOPS,BBU保障断电数据安全 |
| RAID级别 | RAID 10 | 不要用RAID 5,RAID 10性能更优 |
2.2 BBU(电池备份单元)作用
- CACHE Memory:RAID卡内置128MB-1GB缓存,提升读写性能
- BBU电池:断电时保护缓存数据不丢失,直至电源恢复
三、文件系统层优化
3.1 I/O调度器选择
# 查看当前调度器
cat /sys/block/sda/queue/scheduler
# 临时修改(重启失效)
echo deadline > /sys/block/sda/queue/scheduler
# 永久修改(CentOS 7+)
grubby --update-kernel=ALL --args="elevator=deadline"
| 调度器 | 适用场景 | 特点 |
|---|---|---|
| deadline | 数据库(MySQL/Oracle) | 确保截止时间内服务请求,防止写饿死 |
| noop | SSD、虚拟化环境 | 简单FIFO,适合智能硬件 |
| cfq | 桌面、多任务 | 完全公平排队,不适合密集I/O |
3.2 文件系统选择
# 推荐使用XFS
mkfs.xfs /dev/sdb1
# 挂载选项(重要!)
mount -o noatime,nodiratime,nobarrier /dev/sdb1 /data
# 写入fstab
/dev/sdb1 /data xfs defaults,noatime,nodiratime,nobarrier 0 0
| 文件系统 | 适用性 | 说明 |
|---|---|---|
| XFS | 最佳 | 高并发、大文件场景首选 |
| ext4 | 可用 | 中小规模可用 |
| ext3 | 不推荐 | 性能差 |
挂载选项说明:
noatime:不更新文件访问时间nodiratime:不更新目录访问时间nobarrier:XFS特有,禁用写屏障(提升性能)
四、Linux内核参数优化
4.1 swappiness(内存交换)
# 查看当前值
cat /proc/sys/vm/swappiness
# 临时修改
echo 10 > /proc/sys/vm/swappiness
# 永久修改
echo "vm.swappiness = 10" >> /etc/sysctl.conf
sysctl -p

| 值 | 行为 | 推荐 |
|---|---|---|
| 0 | 最大限度使用物理内存 | 不推荐(可能触发OOM) |
| 10 | 内存使用90%后才开始swap | 推荐 |
| 60 | 默认值 | 内存40%时开始swap |
| 100 | 积极使用swap | 不推荐 |
4.2 脏页参数
脏页(Dirty Pages)是什么?
通俗解释
脏页就是内存中被修改过但还没写入磁盘的数据页。就像你在纸上写了字但还没保存到文件,这页纸就是“脏”的。
技术定义
当应用程序修改数据时,MySQL先把数据读到内存(Buffer Pool)里修改,这时内存中的页面就和磁盘上的页面不一致了——内存里的页面就是“脏页”。
vm.dirty_background_ratio:这个参数指定了当文件系统缓存脏页数量达到系统内存百分之多少时(如5%)就会触发pdflush/flush/kdmflush等后台回写进程运行,将一定缓存的脏页异步地刷入外存;
vm.dirty_ratio:这个参数则指定了当文件系统缓存脏页数量达到系统内存百分之多少时(如10%),系统不得不开始处理缓存脏页(因为此时脏页数量已经比较多,为了避免数据丢失需要将一定脏页刷入磁盘);在此过程中很多应用进程可能会出现IO阻塞。
将vm.dirty_background_ratio设置为5-10,将vm.dirty_ratio设置为它的两倍左右,以确保能持续将脏数据刷新到磁盘,避免瞬间I/O写,产生严重等待。
# 查看当前值
cat /proc/sys/vm/dirty_background_ratio
cat /proc/sys/vm/dirty_ratio
# 临时修改
echo 5 > /proc/sys/vm/dirty_background_ratio
echo 10 > /proc/sys/vm/dirty_ratio
# 永久修改
echo "vm.dirty_background_ratio = 5" >> /etc/sysctl.conf
echo "vm.dirty_ratio = 10" >> /etc/sysctl.conf
sysctl -p
| 参数 | 含义 | 推荐值 |
|---|---|---|
| dirty_background_ratio | 后台写回阈值 | 5-10 |
| dirty_ratio | 强制写回阈值 | dirty_background_ratio的2倍 |
五、MySQL参数优化
5.1 InnoDB核心参数
(1)、innodb_buffer_pool_size
设置数据和索引缓存的大小,如果是单实例且绝大多数是InnoDB引擎表的话,可考虑设置为物理内存的20%-65%左右,为什么有一个20%呢?对于<4gb的mysql用服务器来说按照20%系统内存来设置,如果物理内存是128gb,此值建议设置为72G。
(2)、innodb_log_file_size
这个值是配置redo log日志的大小,此参数没有一个绝对的概念,如果对Innodb数据表有大量的写入操作,那么选择合适的innodb_log_file_size 值对提升MySQL性能很重要。然而设置太大了,就会增加恢复的时间,因此在MySQL崩溃或者突然断电等情况会令MySQL服务器花很长时间来恢复。
Redo log的空间通过innodb_log_file_size和innodb_log_files_in_group(默认2)参数来调节。将这俩参数相乘即可得到总的可用Redo log 空间。尽管技术上并不关心你是通过innodb_log_file_size还是innodb_log_files_in_group来调整Redo log空间,不过多数情况下还是通过innodb_log_file_size 来调节。
(3)、innodb_log_buffer_size
这个配置决定了为尚未执行的事务分配的缓存。其默认值(1MB)一般来说已经够用了,但是如果事务中包含有二进制大对象或者大文本字段的话,这点缓存很快就会被填满并触发额外的I/O操作。看看Innodb_log_waits状态变量,如果它不是0,就需要增加innodb_log_buffer_size。缓冲区更大能提高性能,但意外的故障可能导致数据丢失。
[mysqld]
# 缓冲池大小(最重要!)
innodb_buffer_pool_size = 72G # 物理内存128G时建议72G
# Redo日志
innodb_log_file_size = 2G # 根据写入负载调整
innodb_log_files_in_group = 2 # 默认2个文件组
innodb_log_buffer_size = 16M # 默认1M,如有大事务可增加
# 事务提交方式
innodb_flush_log_at_trx_commit = 1 # 主库用1,从库可用2
innodb_flush_log_at_trx_commit
此参数控制事务的提交方式,也就是控制log的刷新到磁盘的方式。默认值是1.
这个参数只有3个值(0,1,2),性能更高的可以设置为0或是2,这样可以适当的减少磁盘IO(但会丢失一秒钟的事务。),游戏库的MySQL建议设置为0。主库请不要更改。
其中:
0:log buffer中的数据将以每秒一次的频率写入到log file中,且同时会进行文件系统到磁盘的同步操作,但是每个事务的commit并不会触发任何log buffer 到log file的刷新或者文件系统到磁盘的刷新操作;
1:(默认为1)在每次事务提交的时候将log buffer中的数据都会写入到log file,同时也会触发文件系统到磁盘的同步;
2:事务提交会触发log buffer到log file的刷新,但并不会触发磁盘文件系统到磁盘的同步。此外,每秒会有一次文件系统到磁盘同步操作。对于slave节点这个值是可以接受的。
innodb_flush_log_at_trx_commit取值:
| 值 | 行为 | 安全性 | 性能 | 适用 |
|---|---|---|---|---|
| 1 | 每次提交都刷盘 | 最高 | 最低 | 主库推荐 |
| 2 | 每秒刷盘 | 中等 | 高 | 从库/游戏库 |
| 0 | 每秒写日志并刷盘 | 最低 | 最高 | 可丢数据的场景 |
5.2 连接与网络参数
skip_name_resolve
生产上建议开启成1,这样mysql server不会对客户端连接使用反向dns解析,否则经常会出现客户端连上后有timeout现象,如果设成了1带来的问题就是你不能在mysql中使用主机名来对客户端权限进行划分,而是需要使用ip。
tmp_table_size
设置临时表的大小,例如在做高级GROUP BY操作时,会生成临时表。默认系统为32M,如果临时表越来越多,加在一起超过了这个值,那么mysql就会在系统磁盘上创建,这个值不是越大越好,也没有一个合适的值。一开始建议设置为64M,后面根据情况进行调整。
[mysqld]
# 最大连接数
max_connections = 2000 # 建议不超过20000,默认时不超过4096,所以要改限制
# 禁用DNS反向解析
skip_name_resolve = 1 # 避免连接超时
# 最大允许数据包
max_allowed_packet = 256M # 导入大文件时调整
# 临时表大小
tmp_table_size = 64M # 根据group by等操作调整
5.3 系统限制配置
max_connections
此参数用来配置mysql的最大连接数,如果看到‘Too many connections’错误,就表示max_connections的值太低了。
根据mysql服务器硬件配置不同,此值可设置的大小也不同,生产环境上建议设置不超过20000。max_connections值受系统Linux系统最大打开连接数限制,因此我们需要做以操作:
1)在 /etc/security/limits.conf 底部增加2行
mysql hard nofile 65535
mysql soft nofile 65535
2)在/usr/lib/systemd/system/mysqld.service(视如何安装mysql所决定,用编译安装和yum安装会产生path路径不同。)文件最后添加:
LimitNOFILE=65535
LimitNPROC=65535
systemctl daemon-reload
systemctl restart mysqld.service
# 1. 修改limits.conf
cat >> /etc/security/limits.conf << EOF
mysql soft nofile 65535
mysql hard nofile 65535
EOF
# 2. 修改systemd服务文件
cat >> /usr/lib/systemd/system/mysqld.service << EOF
LimitNOFILE=65535
LimitNPROC=65535
EOF
# 3. 重载配置
systemctl daemon-reload
systemctl restart mysqld
5.4 主从复制参数
gtid_mode
gtid_mode:主从复制时用,推荐开启成on,也就是开启了GTID模式,GTID(Global Transaction ID)是对于一个已提交事务的编号,并且是一个全局唯一的编号。GTID实际上是由UUID+TID组成的。其中UUID是一个MySQL实例的唯一标识,保存在mysql数据目录下的auto.cnf文件里。TID代表了该实例上已经提交的事务数量,并且随着事务提交单调递增。相比传统的复制,GTID复制对于运维更加友好,根据GTID可以知道事务最初是在哪个实例上提交的,产生多少事物等,都可以非常直接的标识出来。
log_bin
开启二进制日志记录功能,如果你想让数据库服务器充当主节点,那么必须开启二进制日志记录功能。
[mysqld]
# 开启GTID模式(推荐)
gtid_mode = ON
enforce_gtid_consistency = ON
# 开启二进制日志(主库必须)
log_bin = /var/log/mysql/mysql-bin.log
binlog_format = ROW
5.5 其他重要参数
| 参数 | 推荐值 | 说明 |
|---|---|---|
| innodb_io_capacity | 2000 | SSD可设更高 |
| innodb_read_io_threads | 64 | 读线程数 |
| innodb_write_io_threads | 64 | 写线程数 |
| innodb_flush_method | O_DIRECT | 绕过文件系统缓存 |
| transaction_isolation | READ-COMMITTED | 适合高并发 |
六、优化效果监控
-- 查看InnoDB状态
SHOW ENGINE INNODB STATUS\G
-- 查看缓存命中率
SHOW STATUS LIKE 'Innodb_buffer_pool_read%';
-- 查看连接数
SHOW VARIABLES LIKE 'max_connections';
SHOW STATUS LIKE 'Threads_connected';
-- 查看慢查询
SHOW VARIABLES LIKE 'slow_query_log%';
一句话总结
MySQL优化是一个系统工程:硬件选型是基础,文件系统和内核参数是支撑,MySQL自身配置是核心,三者缺一不可!
生产环境调优版
[Unit]
Description=MySQL Server
Documentation=https://dev.mysql.com/doc/
After=network.target
After=syslog.target
Wants=network-online.target
[Service]
User=mysql
Group=mysql
Type=forking
PIDFile=/usr/local/mysql/logs/mysqld.pid
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/usr/local/mysql/etc/my.cnf --daemonize --pid-file=/usr/local/mysql/logs/mysqld.pid
ExecStop=/usr/local/mysql/bin/mysqladmin -u root -p${MYSQL_ROOT_PASSWORD} shutdown
ExecReload=/bin/kill -HUP $MAINPID
# ========== 重启策略调优 ==========
Restart=on-failure
RestartSec=10
StartLimitBurst=5 # 5分钟内最多重启5次
StartLimitIntervalSec=300 # 超过限制则不再重启
# ========== CPU 调优 ==========
CPUQuota=400% # 限制最多使用4个CPU核心
CPUWeight=1000 # CPU优先级(默认100,越高越优先)
CPUSchedulingPolicy=rr # 调度策略:rr(轮询)/fifo(先进先出)/other
CPUSchedulingPriority=89 # 实时优先级(1-99,越高越优先)
Nice=-5 # nice值(-20~19,越小优先级越高)
# ========== 内存调优 ==========
MemoryMax=32G # 最大内存限制(硬限制)
MemoryHigh=28G # 内存使用高水位(软限制)
MemoryLimit=32G # 内存限制(旧版本)
MemorySwapMax=2G # 最大swap使用量
# ========== I/O 调优 ==========
IOWeight=1000 # IO优先级(默认100,越高越优先)
IOSchedulingClass=2 # IO调度类:0(无),1(实时),2(尽力),3(空闲)
IOSchedulingPriority=7 # IO优先级(0-7,0最高)
# ========== 文件句柄调优 ==========
LimitNOFILE=1048576 # 最大打开文件数(高并发必备)
LimitNPROC=65535 # 最大进程数
LimitCORE=infinity # core文件大小
LimitAS=infinity # 地址空间限制
LimitRSS=infinity # 内存驻留集大小
LimitMEMLOCK=infinity # 内存锁定限制
# ========== 任务/线程调优 ==========
TasksMax=infinity # 最大任务数
Delegate=yes # 允许服务管理自己的cgroup
# ========== 安全隔离调优 ==========
PrivateTmp=true
PrivateDevices=true # 隔离设备访问
PrivateNetwork=false # 是否需要私有网络
ProtectSystem=full # 保护系统目录(/usr /boot)
ProtectHome=true # 保护家目录
ProtectKernelTunables=true # 保护内核参数
ProtectKernelModules=true # 禁止加载内核模块
ProtectControlGroups=true # 保护cgroup
NoNewPrivileges=true
RestrictRealtime=true # 限制实时调度
RestrictNamespaces=true # 限制namespace
# ========== 系统调用过滤 ==========
SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module mount @obsolete @raw-io setdomainname setgroups sethostname
SystemCallArchitectures=native
# ========== OOM Killer 调优 ==========
OOMScoreAdjust=-500 # OOM分数(-1000~1000,越低越不易被kill)
# ========== 日志调优 ==========
StandardOutput=journal
StandardError=journal
SyslogIdentifier=mysqld
SyslogFacility=daemon
SyslogLevel=info
# ========== 环境变量 ==========
Environment=MYSQL_ROOT_PASSWORD=your_password_here
Environment=LD_PRELOAD=/usr/lib64/libjemalloc.so # 使用jemalloc优化内存
[Install]
WantedBy=multi-user.target
发表回复