MySQL 硬件优化和操作系统优化

MySQL 硬件优化和操作系统优化

MySQL 体系结构:https://blog.csdn.net/a18792721831/article/details/156569942

MySQL 主从复制:https://blog.csdn.net/a18792721831/article/details/146117935

MySQL Binlog:https://blog.csdn.net/a18792721831/article/details/146606305

MySQL Redo Log:https://blog.csdn.net/a18792721831/article/details/149862528

MySQL 索引优化:https://blog.csdn.net/a18792721831/article/details/150282163

MySQL 锁:https://blog.csdn.net/a18792721831/article/details/154197322

MySQL 事务:https://blog.csdn.net/a18792721831/article/details/156461289

MySQL 硬件优化和操作系统优化

数据库性能优化是一个系统工程,除了 SQL 优化、索引优化、参数调优之外,硬件选型操作系统配置同样至关重要。很多时候,硬件和 OS 层面的优化能带来比 SQL 优化更显著的性能提升。

本文将从硬件选择、RAID 配置、文件系统、内核参数、多实例资源隔离等方面,深入讲解 MySQL 的底层优化策略。

硬件优化

硬件选择

MySQL 是一个 I/O 密集型 + CPU 密集型 的应用,硬件选择需要综合考虑 CPU、内存、存储三个维度。

CPU 选择

CPU 对 MySQL 性能的影响:

场景 CPU 需求 说明
OLTP(在线事务处理) 高主频 单条 SQL 执行依赖单核性能
OLAP(在线分析处理) 多核心 复杂查询可并行执行
高并发连接 多核心 每个连接一个线程
排序/聚合操作 高主频 + 大缓存 计算密集型操作

选择建议:

  1. OLTP 场景优先选择高主频 CPU

    • MySQL 的大部分操作是单线程的(一条 SQL 由一个线程执行)
    • 主频越高,单条 SQL 执行越快
    • 推荐:Intel Xeon Platinum 8255C(2.5GHz)或更高主频
  2. 核心数根据并发量选择

    • 一般 8-16 核足够大多数场景
    • 高并发场景可选择 32 核以上
    • MySQL 8.0 对多核优化更好
  3. 开启超线程(Hyper-Threading)

    • 可提升 15-30% 的并发处理能力
    • 但对于 CPU 密集型查询,效果有限
bash 复制代码
# 查看 CPU 信息
lscpu

# 查看 CPU 主频
cat /proc/cpuinfo | grep "MHz"

# 查看是否开启超线程
cat /sys/devices/system/cpu/smt/active
内存选择

内存对 MySQL 性能的影响:

内存是 MySQL 性能的关键因素。InnoDB 的 Buffer Pool 越大,能缓存的数据越多,磁盘 I/O 越少。

内存配置原则:

配置项 建议值 说明
总内存 尽可能大 数据库服务器的核心资源
Buffer Pool 物理内存的 50-80% InnoDB 最重要的内存区域
预留给 OS 至少 2-4GB 文件系统缓存、OS 运行
每连接内存 约 1-4MB sort_buffer、join_buffer 等

计算公式:

复制代码
可用于 MySQL 的内存 = 总内存 - OS 预留 - 其他应用
Buffer Pool = 可用内存 × 70-80%

示例:

对于 32GB 内存的服务器:

  • OS 预留:4GB
  • 可用于 MySQL:28GB
  • Buffer Pool:20-22GB(innodb_buffer_pool_size = 20G
sql 复制代码
-- 查看 Buffer Pool 大小
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';

-- 查看 Buffer Pool 使用情况
SELECT 
    POOL_ID,
    POOL_SIZE,
    FREE_BUFFERS,
    DATABASE_PAGES,
    PAGES_MADE_YOUNG,
    HIT_RATE
FROM information_schema.INNODB_BUFFER_POOL_STATS;

内存类型选择:

  • 优先选择 DDR4DDR5
  • 选择支持 ECC(Error Correcting Code) 的内存
  • 多通道配置可提升内存带宽
存储选择

存储是 MySQL 性能的最大瓶颈。选择合适的存储设备至关重要。

存储类型对比:

存储类型 随机读 IOPS 随机写 IOPS 顺序读带宽 延迟 价格
HDD(机械硬盘) 100-200 100-200 100-200 MB/s 5-10ms
SATA SSD 50,000-100,000 30,000-80,000 500-550 MB/s 0.1ms
NVMe SSD 500,000-1,000,000 200,000-500,000 3-7 GB/s 0.02ms
Intel Optane 500,000+ 500,000+ 2-3 GB/s 0.01ms 很高

选择建议:

  1. OLTP 场景必须使用 SSD

    • 随机 I/O 性能是 HDD 的 100-1000 倍
    • 推荐 NVMe SSD
  2. 数据文件和日志文件分离

    • Redo Log 放在高性能 SSD(写密集)
    • 数据文件可放在普通 SSD
  3. 考虑写入寿命(TBW)

    • 数据库写入量大,选择企业级 SSD
    • 关注 DWPD(Drive Writes Per Day)指标
bash 复制代码
# 查看磁盘信息
lsblk -d -o NAME,SIZE,ROTA,TYPE

# ROTA=0 表示 SSD,ROTA=1 表示 HDD

# 使用 fio 测试磁盘性能
# 随机读测试
fio --name=randread --ioengine=libaio --iodepth=32 --rw=randread \
    --bs=4k --direct=1 --size=1G --numjobs=4 --runtime=60 --filename=/data/fio_test

# 随机写测试
fio --name=randwrite --ioengine=libaio --iodepth=32 --rw=randwrite \
    --bs=4k --direct=1 --size=1G --numjobs=4 --runtime=60 --filename=/data/fio_test

RAID 的选择

RAID(Redundant Arrays of Independent Disks,独立磁盘冗余阵列) 是通过多块磁盘组合来提升性能和可靠性的技术。

常见 RAID 级别对比
RAID 级别 最少磁盘数 数据冗余 读性能 写性能 空间利用率 适用场景
RAID 0 2 最高 最高 100% 临时数据、缓存
RAID 1 2 镜像 50% 系统盘、日志
RAID 5 3 1块校验 (n-1)/n 读多写少
RAID 6 4 2块校验 (n-2)/n 高可靠性
RAID 10 4 镜像+条带 最高 50% 数据库推荐
MySQL RAID 配置建议
复制代码
┌─────────────────────────────────────────────────────────┐
│                    MySQL RAID 架构                       │
├─────────────────────────────────────────────────────────┤
│                                                         │
│   系统盘 (OS + MySQL 二进制)                             │
│   └─ RAID 1 (2块 SSD)                                   │
│      - 高可靠性                                          │
│      - 系统启动快                                        │
│                                                         │
│   数据盘 (数据文件 + 索引)                               │
│   └─ RAID 10 (4块或更多 SSD)                            │
│      - 高性能 + 高可靠性                                 │
│      - 随机 I/O 性能最佳                                 │
│                                                         │
│   日志盘 (Redo Log + Binlog)                            │
│   └─ RAID 1 (2块高性能 SSD)                             │
│      - 顺序写为主                                        │
│      - 写入性能关键                                      │
│                                                         │
└─────────────────────────────────────────────────────────┘

配置建议:

  1. 数据文件使用 RAID 10

    • 兼顾性能和可靠性
    • 随机读写性能最佳
    • 可承受单块磁盘故障
  2. Redo Log 使用 RAID 1 或单独的高性能 SSD

    • 顺序写为主,RAID 1 足够
    • 写入延迟要求高
  3. Binlog 可与 Redo Log 共用或单独存放

    • 顺序写为主
    • 对延迟要求不如 Redo Log 高
  4. 开启 RAID 卡的写缓存(BBU/电池保护)

    • 显著提升写入性能
    • 必须有电池保护,防止断电数据丢失
bash 复制代码
# 查看 RAID 信息(以 MegaRAID 为例)
megacli -LDInfo -Lall -aALL

# 查看 RAID 卡缓存策略
megacli -LDGetProp -Cache -Lall -aALL

# 查看 BBU 状态
megacli -AdpBbuCmd -GetBbuStatus -aALL
RAID 写惩罚

不同 RAID 级别的写操作开销不同:

RAID 级别 写惩罚 说明
RAID 0 1 无冗余,直接写
RAID 1 2 写入两份镜像
RAID 5 4 读旧数据+读校验+写数据+写校验
RAID 6 6 比 RAID 5 多一次校验计算
RAID 10 2 每条带写两份镜像

计算实际 IOPS:

复制代码
实际写 IOPS = 磁盘总 IOPS / 写惩罚

例如:4 块 SSD(每块 50000 IOPS)组成 RAID 10

  • 总 IOPS:200000
  • 写惩罚:2
  • 实际写 IOPS:100000

操作系统的优化

文件系统的选择

文件系统的选择直接影响 MySQL 的 I/O 性能。

常见文件系统对比
文件系统 特点 优点 缺点 推荐场景
XFS 高性能、可扩展 大文件性能好、并发写入优秀 删除大量小文件慢 MySQL 推荐
ext4 稳定、成熟 兼容性好、小文件性能好 大文件性能不如 XFS 通用场景
Btrfs 写时复制、快照 支持快照、压缩 性能不稳定 不推荐生产
ZFS 企业级特性 数据完整性、压缩、快照 内存占用大 特殊场景
MySQL 文件系统推荐

推荐使用 XFS,原因如下:

  1. 大文件性能优秀

    • InnoDB 数据文件通常很大
    • XFS 对大文件的顺序读写优化好
  2. 并发写入性能好

    • 支持延迟分配(delayed allocation)
    • 多线程写入不会相互阻塞
  3. 在线扩容

    • 支持在线扩展文件系统大小
  4. Linux 内核原生支持

    • RHEL/CentOS 7+ 默认文件系统

XFS 挂载选项优化:

bash 复制代码
# 推荐的 XFS 挂载选项
/dev/vdb /data xfs defaults,noatime,nodiratime,nobarrier 0 0
选项 说明
noatime 不更新文件访问时间,减少写操作
nodiratime 不更新目录访问时间
nobarrier 禁用写屏障(需要 RAID 卡有 BBU)

注意: nobarrier 选项在有电池保护的 RAID 卡上可以安全使用,否则可能导致数据丢失。

bash 复制代码
# 查看当前挂载选项
mount | grep /data

# 查看文件系统类型
df -T /data

# 创建 XFS 文件系统
mkfs.xfs -f /dev/vdb

# 挂载 XFS
mount -o defaults,noatime,nodiratime /dev/vdb /data

系统参数的选择

Linux 内核参数对 MySQL 性能有重要影响。以下是关键参数的优化建议。

内存相关参数

1. vm.swappiness

控制系统使用 swap 的倾向。

bash 复制代码
# 查看当前值
sysctl vm.swappiness

# 推荐设置为 1-10(MySQL 场景)
sysctl -w vm.swappiness=1

# 永久生效
echo "vm.swappiness = 1" >> /etc/sysctl.conf
说明
0 仅在内存不足时使用 swap
1-10 MySQL 推荐,尽量避免 swap
60 默认值,积极使用 swap
100 积极使用 swap

为什么 MySQL 要避免 swap?

  • swap 会导致严重的性能下降
  • InnoDB Buffer Pool 被 swap 出去会导致大量磁盘 I/O
  • 宁可 OOM 也不要 swap

2. vm.dirty_ratio 和 vm.dirty_background_ratio

控制脏页(dirty page)的刷新策略。

bash 复制代码
# 查看当前值
sysctl vm.dirty_ratio
sysctl vm.dirty_background_ratio

# 推荐设置
sysctl -w vm.dirty_ratio=10
sysctl -w vm.dirty_background_ratio=5

# 永久生效
echo "vm.dirty_ratio = 10" >> /etc/sysctl.conf
echo "vm.dirty_background_ratio = 5" >> /etc/sysctl.conf
参数 默认值 推荐值 说明
vm.dirty_ratio 40 10 脏页占内存比例达到此值时,进程阻塞等待刷盘
vm.dirty_background_ratio 10 5 脏页占内存比例达到此值时,后台开始刷盘

3. vm.overcommit_memory

控制内存过量分配策略。

bash 复制代码
# 查看当前值
sysctl vm.overcommit_memory

# 推荐设置为 0 或 2
sysctl -w vm.overcommit_memory=0
说明
0 默认,启发式过量分配
1 总是允许过量分配(危险)
2 不允许过量分配,限制为 swap + 物理内存 × ratio
透明大页(Transparent Huge Pages)

必须禁用透明大页!

透明大页(THP)会导致 MySQL 性能问题:

  • 内存分配延迟增加
  • 内存碎片化
  • 随机的性能抖动
bash 复制代码
# 查看当前状态
cat /sys/kernel/mm/transparent_hugepage/enabled
cat /sys/kernel/mm/transparent_hugepage/defrag

# 临时禁用
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

# 永久禁用(添加到 /etc/rc.local 或 systemd 服务)

永久禁用方法(systemd):

创建 /etc/systemd/system/disable-thp.service

ini 复制代码
[Unit]
Description=Disable Transparent Huge Pages (THP)
DefaultDependencies=no
After=sysinit.target local-fs.target
Before=mysqld.service

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo never > /sys/kernel/mm/transparent_hugepage/enabled && echo never > /sys/kernel/mm/transparent_hugepage/defrag'

[Install]
WantedBy=basic.target
bash 复制代码
# 启用服务
systemctl daemon-reload
systemctl enable disable-thp
systemctl start disable-thp
I/O 调度器

I/O 调度器决定了磁盘 I/O 请求的处理顺序。

常见 I/O 调度器:

调度器 特点 适用场景
mq-deadline 保证请求延迟,适合数据库 SSD + MySQL 推荐
none/noop 不做调度,直接下发 NVMe SSD
bfq 公平带宽分配 桌面系统
kyber 低延迟优化 高性能 SSD
bash 复制代码
# 查看当前调度器
cat /sys/block/vda/queue/scheduler

# 临时修改
echo mq-deadline > /sys/block/vda/queue/scheduler

# 永久修改(添加到 /etc/udev/rules.d/60-scheduler.rules)
ACTION=="add|change", KERNEL=="sd*", ATTR{queue/scheduler}="mq-deadline"
ACTION=="add|change", KERNEL=="nvme*", ATTR{queue/scheduler}="none"

对于 NVMe SSD:

  • 推荐使用 nonemq-deadline
  • NVMe 本身有硬件队列,内核调度意义不大
文件描述符限制

MySQL 需要大量文件描述符(每个连接、每个表文件都需要)。

bash 复制代码
# 查看当前限制
ulimit -n

# 查看系统最大值
cat /proc/sys/fs/file-max

# 修改用户限制(/etc/security/limits.conf)
mysql soft nofile 65535
mysql hard nofile 65535

# 修改系统最大值
sysctl -w fs.file-max=6553560

推荐配置:

bash 复制代码
# /etc/security/limits.conf
mysql soft nofile 65535
mysql hard nofile 65535
mysql soft nproc 65535
mysql hard nproc 65535
网络参数优化

对于高并发 MySQL 服务器,网络参数也需要优化:

bash 复制代码
# /etc/sysctl.conf

# 增加 TCP 连接队列
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535

# 增加端口范围
net.ipv4.ip_local_port_range = 1024 65535

# TCP 连接复用
net.ipv4.tcp_tw_reuse = 1

# 增加网络缓冲区
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
完整的 sysctl 配置示例
bash 复制代码
# /etc/sysctl.conf - MySQL 优化配置

# 内存相关
vm.swappiness = 1
vm.dirty_ratio = 10
vm.dirty_background_ratio = 5
vm.overcommit_memory = 0

# 文件系统
fs.file-max = 6553560
fs.aio-max-nr = 1048576

# 网络相关
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_tw_reuse = 1
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216

# 应用配置
sysctl -p

MySQL 多实例资源隔离优化

在同一台服务器上运行多个 MySQL 实例时,需要进行资源隔离,避免实例之间相互影响。

资源隔离的必要性
问题 影响 解决方案
CPU 争抢 某实例 CPU 占用过高影响其他实例 CPU 绑定/cgroups
内存争抢 OOM 或 swap 影响所有实例 内存限制
I/O 争抢 磁盘 I/O 带宽被某实例占满 I/O 限制
网络争抢 网络带宽被某实例占满 网络 QoS
cgroups 资源隔离

cgroups(Control Groups) 是 Linux 内核提供的资源隔离机制。

cgroups v1 vs v2:

特性 cgroups v1 cgroups v2
层级结构 多层级,每个控制器独立 单一层级
配置方式 各控制器目录分散 统一目录结构
资源控制 各控制器独立配置 统一接口
推荐版本 旧系统 新系统推荐

检查 cgroups 版本:

bash 复制代码
# 检查是否支持 cgroups v2
cat /sys/fs/cgroup/cgroup.controllers 2>/dev/null && echo "cgroups v2" || echo "cgroups v1"

# 查看挂载的 cgroups
mount | grep cgroup
cgroups v1 配置(传统方式)

CPU 限制:

bash 复制代码
# 创建 cgroup
mkdir -p /sys/fs/cgroup/cpu/mysql_instance1

# 限制 CPU 使用率为 50%(相对于单核)
echo 50000 > /sys/fs/cgroup/cpu/mysql_instance1/cpu.cfs_quota_us
echo 100000 > /sys/fs/cgroup/cpu/mysql_instance1/cpu.cfs_period_us

# 绑定到特定 CPU 核心
mkdir -p /sys/fs/cgroup/cpuset/mysql_instance1
echo "0-3" > /sys/fs/cgroup/cpuset/mysql_instance1/cpuset.cpus
echo "0" > /sys/fs/cgroup/cpuset/mysql_instance1/cpuset.mems

# 将进程加入 cgroup
echo <mysql_pid> > /sys/fs/cgroup/cpu/mysql_instance1/tasks

内存限制:

bash 复制代码
# 创建 cgroup
mkdir -p /sys/fs/cgroup/memory/mysql_instance1

# 限制内存为 4GB
echo 4294967296 > /sys/fs/cgroup/memory/mysql_instance1/memory.limit_in_bytes

# 限制内存 + swap 总量
echo 4294967296 > /sys/fs/cgroup/memory/mysql_instance1/memory.memsw.limit_in_bytes

# 将进程加入 cgroup
echo <mysql_pid> > /sys/fs/cgroup/memory/mysql_instance1/tasks

I/O 限制:

bash 复制代码
# 创建 cgroup
mkdir -p /sys/fs/cgroup/blkio/mysql_instance1

# 限制读写带宽(设备号:major:minor 读带宽 字节/秒)
# 查看设备号:ls -l /dev/vdb
echo "253:16 104857600" > /sys/fs/cgroup/blkio/mysql_instance1/blkio.throttle.read_bps_device
echo "253:16 52428800" > /sys/fs/cgroup/blkio/mysql_instance1/blkio.throttle.write_bps_device

# 限制 IOPS
echo "253:16 1000" > /sys/fs/cgroup/blkio/mysql_instance1/blkio.throttle.read_iops_device
echo "253:16 500" > /sys/fs/cgroup/blkio/mysql_instance1/blkio.throttle.write_iops_device
cgroups v2 配置(推荐)

cgroups v2 提供了统一的接口,配置更简洁。

启用 cgroups v2:

bash 复制代码
# 在 GRUB 中添加参数
# /etc/default/grub
GRUB_CMDLINE_LINUX="systemd.unified_cgroup_hierarchy=1"

# 更新 GRUB
grub2-mkconfig -o /boot/grub2/grub.cfg

# 重启系统
reboot

创建和配置 cgroup:

bash 复制代码
# 创建 cgroup
mkdir -p /sys/fs/cgroup/mysql_instance1

# 启用控制器
echo "+cpu +memory +io" > /sys/fs/cgroup/cgroup.subtree_control

# CPU 限制(50% of 4 cores = 200000/100000)
echo "200000 100000" > /sys/fs/cgroup/mysql_instance1/cpu.max

# 内存限制(4GB)
echo "4294967296" > /sys/fs/cgroup/mysql_instance1/memory.max
echo "4294967296" > /sys/fs/cgroup/mysql_instance1/memory.swap.max

# I/O 限制(设备号 读带宽 写带宽 读IOPS 写IOPS)
echo "253:16 rbps=104857600 wbps=52428800 riops=1000 wiops=500" > /sys/fs/cgroup/mysql_instance1/io.max

# 将进程加入 cgroup
echo <mysql_pid> > /sys/fs/cgroup/mysql_instance1/cgroup.procs

cgroups v2 配置文件说明:

文件 说明 示例
cpu.max CPU 限制(quota period) 200000 100000 = 200% CPU
memory.max 内存硬限制 4294967296 = 4GB
memory.high 内存软限制(触发回收) 3221225472 = 3GB
io.max I/O 带宽和 IOPS 限制 253:16 rbps=100M wbps=50M
NUMA 绑定优化

NUMA(Non-Uniform Memory Access) 是多处理器系统的内存架构。在 NUMA 系统中,每个 CPU 有自己的本地内存,访问本地内存比访问远程内存更快。

查看 NUMA 拓扑:

bash 复制代码
# 查看 NUMA 节点信息
numactl --hardware

# 查看 NUMA 统计
numastat

# 查看进程的 NUMA 分布
numastat -p <pid>

NUMA 绑定策略:

策略 说明 适用场景
--cpunodebind 绑定到指定 NUMA 节点的 CPU 限制 CPU 使用
--membind 绑定到指定 NUMA 节点的内存 限制内存分配
--interleave 内存交错分配到所有节点 大内存应用
--preferred 优先使用指定节点,不够时使用其他 一般场景

MySQL NUMA 绑定示例:

bash 复制代码
# 将 MySQL 绑定到 NUMA node 0
numactl --cpunodebind=0 --membind=0 mysqld

# 或者使用 Docker 启动时绑定
docker run -d \
  --cpuset-cpus="0-3" \
  --cpuset-mems="0" \
  --name mysql-numa \
  -e MYSQL_ROOT_PASSWORD=root \
  mysql:8.0

# 查看容器的 NUMA 绑定状态
docker inspect mysql-numa --format "CPUSet: {{.HostConfig.CpusetCpus}}, MemSet: {{.HostConfig.CpusetMems}}"

NUMA 优化建议:

  1. 单实例场景

    • 如果 MySQL 内存需求小于单个 NUMA 节点的内存,绑定到一个节点
    • 如果内存需求大,使用 --interleave=all
  2. 多实例场景

    • 每个实例绑定到不同的 NUMA 节点
    • 避免跨节点内存访问
  3. InnoDB 配置

    • 设置 innodb_numa_interleave=1(MySQL 5.7.9+)
    • Buffer Pool 会交错分配到所有 NUMA 节点
sql 复制代码
-- 查看 NUMA 相关配置
SHOW VARIABLES LIKE '%numa%';
Docker 资源限制

在 Docker 中运行 MySQL 时,可以通过 Docker 的资源限制功能实现隔离。

CPU 限制:

bash 复制代码
# 限制 CPU 使用率(相对于所有核心)
docker run -d \
  --cpus="2.0" \
  mysql:8.0

# 绑定到特定 CPU 核心
docker run -d \
  --cpuset-cpus="0-3" \
  mysql:8.0

# CPU 份额(相对权重)
docker run -d \
  --cpu-shares=1024 \
  mysql:8.0

内存限制:

bash 复制代码
# 限制内存为 4GB
docker run -d \
  --memory=4g \
  --memory-swap=4g \
  mysql:8.0

# 内存预留(软限制)
docker run -d \
  --memory=4g \
  --memory-reservation=2g \
  mysql:8.0

I/O 限制:

bash 复制代码
# 限制块设备读写带宽
docker run -d \
  --device-read-bps /dev/vdb:100mb \
  --device-write-bps /dev/vdb:50mb \
  mysql:8.0

# 限制块设备 IOPS
docker run -d \
  --device-read-iops /dev/vdb:1000 \
  --device-write-iops /dev/vdb:500 \
  mysql:8.0

完整的 Docker MySQL 资源限制示例:

bash 复制代码
docker run -d \
  --name mysql_instance1 \
  --cpus="4.0" \
  --cpuset-cpus="0-3" \
  --memory=8g \
  --memory-swap=8g \
  --device-read-bps /dev/vdb:200mb \
  --device-write-bps /dev/vdb:100mb \
  -e MYSQL_ROOT_PASSWORD=password \
  -v /data/mysql/instance1/data:/var/lib/mysql \
  -v /data/mysql/instance1/conf:/etc/mysql/conf.d \
  -p 3306:3306 \
  mysql:8.0

docker-compose 配置示例:

yaml 复制代码
version: '3.8'
services:
  mysql_instance1:
    image: mysql:8.0
    container_name: mysql_instance1
    deploy:
      resources:
        limits:
          cpus: '4.0'
          memory: 8G
        reservations:
          cpus: '2.0'
          memory: 4G
    environment:
      MYSQL_ROOT_PASSWORD: password
    volumes:
      - /data/mysql/instance1/data:/var/lib/mysql
      - /data/mysql/instance1/conf:/etc/mysql/conf.d
    ports:
      - "3306:3306"
    cpuset: "0-3"
资源隔离最佳实践
复制代码
┌─────────────────────────────────────────────────────────┐
│              MySQL 多实例资源隔离架构                     │
├─────────────────────────────────────────────────────────┤
│                                                         │
│   服务器配置:32 核 CPU,128GB 内存,2 个 NUMA 节点        │
│                                                         │
│   ┌─────────────────┐    ┌─────────────────┐           │
│   │   MySQL 实例 1   │    │   MySQL 实例 2   │           │
│   │                 │    │                 │           │
│   │ NUMA Node: 0    │    │ NUMA Node: 1    │           │
│   │ CPU: 0-7        │    │ CPU: 16-23      │           │
│   │ Memory: 32GB    │    │ Memory: 32GB    │           │
│   │ I/O: 100MB/s    │    │ I/O: 100MB/s    │           │
│   │                 │    │                 │           │
│   │ Buffer Pool:    │    │ Buffer Pool:    │           │
│   │ 24GB            │    │ 24GB            │           │
│   └─────────────────┘    └─────────────────┘           │
│                                                         │
│   预留资源:                                             │
│   - OS + 监控:8 核 CPU,32GB 内存                       │
│   - CPU 8-15, 24-31 用于其他服务                         │
│                                                         │
└─────────────────────────────────────────────────────────┘

配置清单:

配置项 实例 1 实例 2
NUMA 节点 0 1
CPU 核心 0-7 16-23
内存限制 32GB 32GB
Buffer Pool 24GB 24GB
I/O 带宽 100MB/s 100MB/s
端口 3306 3307

性能测试与验证

优化效果需要通过性能测试来验证。以下介绍常用的测试工具和方法。

sysbench 基准测试

sysbench 是最常用的 MySQL 基准测试工具。

安装 sysbench:

bash 复制代码
# CentOS/RHEL
yum install -y sysbench

# Ubuntu/Debian
apt-get install -y sysbench

# 验证安装
sysbench --version

OLTP 测试流程:

bash 复制代码
# 1. 准备测试数据
sysbench oltp_read_write \
  --mysql-host=127.0.0.1 \
  --mysql-port=3306 \
  --mysql-user=root \
  --mysql-password=password \
  --mysql-db=sbtest \
  --tables=10 \
  --table-size=1000000 \
  prepare

# 2. 运行测试
sysbench oltp_read_write \
  --mysql-host=127.0.0.1 \
  --mysql-port=3306 \
  --mysql-user=root \
  --mysql-password=password \
  --mysql-db=sbtest \
  --tables=10 \
  --table-size=1000000 \
  --threads=16 \
  --time=300 \
  --report-interval=10 \
  run

# 3. 清理测试数据
sysbench oltp_read_write \
  --mysql-host=127.0.0.1 \
  --mysql-port=3306 \
  --mysql-user=root \
  --mysql-password=password \
  --mysql-db=sbtest \
  --tables=10 \
  cleanup

测试类型说明:

测试类型 说明 适用场景
oltp_read_only 只读测试 读密集型应用
oltp_write_only 只写测试 写密集型应用
oltp_read_write 混合读写 通用 OLTP 场景
oltp_point_select 主键查询 测试索引性能
oltp_insert 插入测试 测试写入性能

关键指标解读:

复制代码
SQL statistics:
    queries performed:
        read:                            1400000
        write:                           400000
        other:                           200000
        total:                           2000000
    transactions:                        100000 (333.33 per sec.)  # TPS
    queries:                             2000000 (6666.67 per sec.) # QPS
    ignored errors:                      0      (0.00 per sec.)
    reconnects:                          0      (0.00 per sec.)

Latency (ms):
         min:                                    2.35
         avg:                                   47.99   # 平均延迟
         max:                                  512.34
         95th percentile:                       89.16   # P95 延迟
         sum:                              4799000.00
指标 说明 优化目标
TPS 每秒事务数 越高越好
QPS 每秒查询数 越高越好
avg latency 平均延迟 越低越好
95th percentile P95 延迟 越低越好

Docker 优化配置对比测试

使用 Docker 启动两个 MySQL 实例,对比默认配置和优化配置的性能差异。

启动默认配置 MySQL:

bash 复制代码
docker run -d --name mysql-default \
    -e MYSQL_ROOT_PASSWORD=root \
    -e MYSQL_DATABASE=sbtest \
    -p 3316:3306 \
    mysql:8.0

启动优化配置 MySQL:

bash 复制代码
docker run -d --name mysql-optimized \
    --cpuset-cpus='0-3' \
    --memory=4g \
    --memory-swap=4g \
    -e MYSQL_ROOT_PASSWORD=root \
    -e MYSQL_DATABASE=sbtest \
    -p 3317:3306 \
    mysql:8.0 \
    --innodb_buffer_pool_size=2G \
    --innodb_log_file_size=512M \
    --innodb_flush_log_at_trx_commit=2 \
    --innodb_flush_method=O_DIRECT \
    --max_connections=500

默认配置 sysbench 测试结果:

优化配置 sysbench 测试结果:

性能对比:

指标 默认配置 优化配置 提升幅度
TPS 620.61 900.81 +45.1%
QPS 12412.12 18016.17 +45.1%
平均延迟 12.89ms 8.88ms -31.1%
P95 延迟 17.63ms 11.87ms -32.7%

通过 CPU 绑定(--cpuset-cpus)、内存限制(--memory)和 InnoDB 参数优化,性能提升显著。

fio 磁盘性能测试

fio 用于测试磁盘 I/O 性能。

bash 复制代码
# 随机读测试(模拟数据库随机查询)
fio --name=randread \
    --ioengine=libaio \
    --iodepth=32 \
    --rw=randread \
    --bs=4k \
    --direct=1 \
    --size=1G \
    --numjobs=4 \
    --runtime=60 \
    --group_reporting \
    --filename=/data/fio_test

# 随机写测试(模拟数据库写入)
fio --name=randwrite \
    --ioengine=libaio \
    --iodepth=32 \
    --rw=randwrite \
    --bs=4k \
    --direct=1 \
    --size=1G \
    --numjobs=4 \
    --runtime=60 \
    --group_reporting \
    --filename=/data/fio_test

# 混合随机读写(70% 读,30% 写)
fio --name=randrw \
    --ioengine=libaio \
    --iodepth=32 \
    --rw=randrw \
    --rwmixread=70 \
    --bs=4k \
    --direct=1 \
    --size=1G \
    --numjobs=4 \
    --runtime=60 \
    --group_reporting \
    --filename=/data/fio_test

监控指标采集

系统级监控:

bash 复制代码
# CPU 使用率
vmstat 1

# 内存使用
free -h

# 磁盘 I/O
iostat -x 1

# 网络流量
sar -n DEV 1

MySQL 级监控:

sql 复制代码
-- 查看 InnoDB 状态
SHOW ENGINE INNODB STATUS\G

-- 查看 Buffer Pool 命中率
SHOW STATUS LIKE 'Innodb_buffer_pool%';

-- 查看连接数
SHOW STATUS LIKE 'Threads%';

-- 查看慢查询
SHOW STATUS LIKE 'Slow_queries';

总结

MySQL 的硬件和操作系统优化是一个系统工程,需要从多个维度进行考虑:

硬件选择:

  1. CPU:OLTP 优先高主频,高并发选择多核心
  2. 内存:越大越好,Buffer Pool 配置为物理内存的 50-80%
  3. 存储:必须使用 SSD,推荐 NVMe,数据和日志分离

RAID 配置:

  1. 数据文件使用 RAID 10
  2. 日志文件使用 RAID 1 或高性能单盘
  3. 开启 RAID 卡写缓存(需要 BBU 保护)

文件系统:

  1. 推荐 XFS 文件系统
  2. 使用 noatime、nodiratime 挂载选项
  3. 有 BBU 的 RAID 卡可使用 nobarrier

内核参数:

  1. vm.swappiness = 1,避免 swap
  2. 禁用透明大页(THP)
  3. I/O 调度器使用 mq-deadline 或 none
  4. 增加文件描述符限制

多实例资源隔离:

  1. 使用 cgroups 限制 CPU、内存、I/O
  2. NUMA 绑定优化内存访问
  3. Docker 资源限制简化管理

在实际工作中,需要根据具体的业务场景和硬件配置,选择合适的优化策略。优化是一个持续的过程,需要不断监控和调整。

相关推荐
CodeAmaz14 小时前
mysql深度分页解决方案大全
mysql·深度分页
BIBI204914 小时前
CentOS 7 安装 MySQL 5.7
linux·mysql·centos·配置·环境搭建·安装教程·服务器运维
只想早点退休的90后14 小时前
sql面试题分享
数据库·sql
华仔啊14 小时前
同事问我 MySQL 用啥排序规则,我差点答不上来
后端·mysql
枫叶丹414 小时前
【Qt开发】Qt系统(三)->事件过滤器
java·c语言·开发语言·数据库·c++·qt
不会c嘎嘎14 小时前
mysql -- 使用CAPI访问mysql服务器
服务器·数据库·mysql
Zzzzmo_14 小时前
【MySQL】数据类型 及 表的操作
数据库·mysql
L16247614 小时前
linux系统中YUM安装MySQL数据库详细教程
linux·数据库·mysql
残风也想永存14 小时前
【MySQL】事务管理
数据库·mysql