0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

MySQL关键参数的最佳配置

马哥Linux运维 来源:马哥Linux运维 2026-01-27 10:32 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一、概述

1.1 背景介绍

运维MySQL数据库十年有余,见过太多因为参数配置不当导致的性能问题。有的公司用着默认配置跑生产环境,128GB内存的服务器上InnoDB缓冲池只有128MB;有的把max_connections设成几万,结果OOM把数据库打挂;还有的sync_binlog设成1,却抱怨写入性能差。

MySQL的可配置参数有数百个,但真正影响性能的核心参数只有二三十个。本文将基于十年运维经验,筛选出20个最关键的参数,详细讲解每个参数的作用原理、取值依据和调优方法。这些参数经过多个大型生产环境的验证,能够覆盖90%以上的调优场景。

本文的目标不是列出一堆参数让人照抄,而是让读者理解每个参数背后的原理,能够根据自己的硬件配置和业务特点,做出正确的调优决策。

1.2 技术特点

MySQL架构与参数关系

             ┌─────────────────────────────────────────────┐
             │       MySQL Server          │
             │ ┌─────────────────────────────────────┐  │
             │ │     Connection Layer       │  │
             │ │ • max_connections          │  │
             │ │ • thread_cache_size         │  │
             │ │ • wait_timeout           │  │
             │ └─────────────────────────────────────┘  │
             │ ┌─────────────────────────────────────┐  │
             │ │     SQL Layer          │  │
             │ │ • sort_buffer_size         │  │
             │ │ • join_buffer_size         │  │
             │ │ • tmp_table_size          │  │
             │ └─────────────────────────────────────┘  │
             │ ┌─────────────────────────────────────┐  │
             │ │    Storage Engine (InnoDB)    │  │
             │ │ • innodb_buffer_pool_size      │  │
             │ │ • innodb_log_file_size       │  │
             │ │ • innodb_flush_log_at_trx_commit  │  │
             │ │ • innodb_io_capacity        │  │
             │ └─────────────────────────────────────┘  │
             └─────────────────────────────────────────────┘
                       │
             ┌───────────────────┴───────────────────┐
             │      Disk I/O          │
             │ • Data Files • Redo Log • Binlog  │
             └────────────────────────────────────────┘

参数分类

分类 参数特点 代表参数
连接类 控制客户端连接行为 max_connections, wait_timeout
内存类 控制各类缓冲区大小 innodb_buffer_pool_size, sort_buffer_size
IO类 控制磁盘读写行为 innodb_io_capacity, sync_binlog
日志类 控制日志记录行为 innodb_log_file_size, binlog_format
复制类 控制主从复制行为 replica_parallel_workers

调优原则

理解为先:先理解参数作用,再调整数值

一次一个:每次只调整一个参数,观察效果

监控验证:调整后必须通过监控验证效果

压测确认:重大调整需在测试环境压测验证

记录变更:所有调整都要记录变更历史

1.3 适用场景

本文的调优建议适用于:

MySQL 8.0.35+ 或 8.4 LTS版本

专用数据库服务器(非混合部署)

16GB以上内存的服务器

SSD/NVMe存储环境

OLTP为主的业务场景

对于以下场景需要特别调整:

OLAP分析型场景:需要增大排序和临时表相关缓冲区

混合部署场景:需要严格限制MySQL内存使用

HDD机械硬盘:IO相关参数需要保守设置

1.4 环境要求

组件 版本要求 说明
MySQL 8.0.35+ / 8.4 LTS 推荐8.4 LTS长期支持版本
操作系统 Rocky 9 / Ubuntu 24.04 内核5.14+支持io_uring
内存 16GB+ 建议专用服务器32GB+
磁盘 NVMe SSD IOPS > 10000
CPU 8核+ 支持超线程
文件系统 XFS/ext4 推荐XFS

二、详细步骤

2.1 准备工作

2.1.1 当前配置检查

调优之前,先了解当前配置状态:

-- 查看关键参数当前值
SELECT
  VARIABLE_NAME,
  VARIABLE_VALUE
FROMperformance_schema.global_variables
WHEREVARIABLE_NAMEIN(
 'innodb_buffer_pool_size',
 'innodb_buffer_pool_instances',
 'innodb_log_file_size',
 'innodb_log_buffer_size',
 'innodb_flush_log_at_trx_commit',
 'innodb_flush_method',
 'innodb_io_capacity',
 'innodb_io_capacity_max',
 'innodb_read_io_threads',
 'innodb_write_io_threads',
 'max_connections',
 'thread_cache_size',
 'table_open_cache',
 'sort_buffer_size',
 'join_buffer_size',
 'tmp_table_size',
 'max_heap_table_size',
 'sync_binlog',
 'binlog_cache_size'
)
ORDERBYVARIABLE_NAME;

2.1.2 硬件信息收集

#!/bin/bash
# collect_hardware_info.sh
# 收集服务器硬件信息

echo"=== MySQL调优信息收集 ==="

echo-e"
[CPU信息]"
lscpu | grep -E"^(CPU(s)|Thread|Core|Socket|Model name)"

echo-e"
[内存信息]"
free -h
cat /proc/meminfo | grep -E"^(MemTotal|MemFree|Cached|Buffers)"

echo-e"
[磁盘信息]"
lsblk -d -o NAME,SIZE,ROTA,TYPE,MODEL
# ROTA=0表示SSD,ROTA=1表示HDD

echo-e"
[磁盘IO能力测试]"
# 使用fio测试4K随机读写IOPS
ifcommand-v fio &> /dev/null;then
 echo"测试4K随机读IOPS..."
  fio --name=randread --ioengine=libaio --direct=1 --bs=4k 
    --iodepth=64 --rw=randread --size=1G --runtime=30 
    --time_based --filename=/tmp/fio_test 
    2>/dev/null | grep -E"(read:|IOPS)"
fi

echo-e"
[MySQL数据目录磁盘使用]"
df -h /var/lib/mysql

echo-e"
[当前MySQL进程内存使用]"
ps aux | grep mysqld | grep -v grep | awk'{print "RSS: " $6/1024 " MB"}'

2.1.3 性能基线记录

-- 记录调优前的性能基线

-- 1. InnoDB缓冲池命中率
SELECT
  (1- (
    (SELECTVARIABLE_VALUEFROMperformance_schema.global_status
    WHEREVARIABLE_NAME ='Innodb_buffer_pool_reads') /
    (SELECTVARIABLE_VALUEFROMperformance_schema.global_status
    WHEREVARIABLE_NAME ='Innodb_buffer_pool_read_requests')
  )) *100ASbuffer_pool_hit_rate;

-- 2. 临时表使用情况
SELECT
  (SELECTVARIABLE_VALUEFROMperformance_schema.global_status
  WHEREVARIABLE_NAME ='Created_tmp_disk_tables') /
  (SELECTVARIABLE_VALUEFROMperformance_schema.global_status
  WHEREVARIABLE_NAME ='Created_tmp_tables') *100
 AStmp_disk_table_pct;

-- 3. 连接使用情况
SELECT
  @@max_connectionsASmax_conn,
  (SELECTVARIABLE_VALUEFROMperformance_schema.global_status
  WHEREVARIABLE_NAME ='Max_used_connections')ASmax_used,
  (SELECTVARIABLE_VALUEFROMperformance_schema.global_status
  WHEREVARIABLE_NAME ='Threads_connected')AScurrent_conn;

-- 4. 慢查询数量
SELECTVARIABLE_VALUEASslow_queries
FROMperformance_schema.global_status
WHEREVARIABLE_NAME ='Slow_queries';

-- 5. 排序和连接相关
SELECT
  gs1.VARIABLE_VALUEASsort_merge_passes,
  gs2.VARIABLE_VALUEASselect_full_join
FROMperformance_schema.global_status gs1,
  performance_schema.global_status gs2
WHEREgs1.VARIABLE_NAME ='Sort_merge_passes'
ANDgs2.VARIABLE_NAME ='Select_full_join';

2.2 核心配置

2.2.1 InnoDB核心参数(参数1-8)

参数1: innodb_buffer_pool_size

这是MySQL最重要的参数,没有之一。InnoDB缓冲池用于缓存数据页和索引页,缓冲池越大,能缓存的数据越多,磁盘IO越少,性能越好。

# 计算公式:物理内存 * 0.7 ~ 0.8(专用服务器)
# 示例:64GB内存服务器
innodb_buffer_pool_size = 48G

取值依据

内存大小 推荐值 说明
8GB 5-6GB 留2-3GB给系统和其他进程
16GB 10-12GB 约70-75%
32GB 22-25GB 约70-80%
64GB 45-50GB 约70-80%
128GB 96-100GB 约75-80%

验证效果

-- 查看缓冲池命中率(应 > 99%)
SHOWGLOBALSTATUSLIKE'Innodb_buffer_pool_read%';

-- 计算命中率
SELECT
 ROUND((1- Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests) *100,2)AShit_rate
FROM(
 SELECT
   SUM(CASEWHENVARIABLE_NAME ='Innodb_buffer_pool_reads'THENCAST(VARIABLE_VALUEASUNSIGNED)END)ASInnodb_buffer_pool_reads,
   SUM(CASEWHENVARIABLE_NAME ='Innodb_buffer_pool_read_requests'THENCAST(VARIABLE_VALUEASUNSIGNED)END)ASInnodb_buffer_pool_read_requests
 FROMperformance_schema.global_status
 WHEREVARIABLE_NAMEIN('Innodb_buffer_pool_reads','Innodb_buffer_pool_read_requests')
)ASstats;

参数2: innodb_buffer_pool_instances

将缓冲池分成多个实例,减少多线程并发访问时的锁竞争。

# 当buffer_pool_size > 1GB时设置
# 建议:每个实例1-2GB,最大不超过64
innodb_buffer_pool_instances = 8

# MySQL 8.0默认已经自动设置合理值
# 当buffer_pool_size < 1GB时,自动设为1

参数3: innodb_log_file_size

InnoDB重做日志文件大小。更大的日志文件可以减少checkpoint频率,提高写入性能,但会增加崩溃恢复时间。

# MySQL 8.0.30+ 使用 innodb_redo_log_capacity 替代
# innodb_redo_log_capacity = innodb_log_file_size * innodb_log_files_in_group * 2

# MySQL 8.0.30之前的配置
innodb_log_file_size = 2G
innodb_log_files_in_group = 2

# MySQL 8.0.30+的配置
innodb_redo_log_capacity = 8G # 相当于之前的4个2G日志文件

取值依据

-- 计算1小时内产生的日志量,以此为基准设置
SHOWENGINEINNODBSTATUSG
-- 查看 Log sequence number 和 Log flushed up to
-- 一小时前后的差值就是每小时日志量

-- 建议设置为能容纳1小时日志量的2-4倍
-- 典型值范围:1GB - 8GB

参数4: innodb_log_buffer_size

重做日志缓冲区大小。事务在提交前先写入日志缓冲区,然后刷盘。

# 默认16MB,大事务场景可适当增大
innodb_log_buffer_size = 64M

什么时候需要增大

-- 查看日志缓冲区等待次数
SHOWGLOBALSTATUSLIKE'Innodb_log_waits';

-- 如果Innodb_log_waits > 0,说明日志缓冲区不够
-- 需要增大innodb_log_buffer_size

参数5: innodb_flush_log_at_trx_commit

这是性能与数据安全的平衡参数,控制redo log的刷盘策略。

# 取值说明:
# 0: 每秒刷盘,事务提交时不刷盘(最快,可能丢1秒数据)
# 1: 每次提交都刷盘(最安全,性能最差)
# 2: 每次提交写OS缓存,每秒刷盘(折中方案)

# 生产环境推荐
innodb_flush_log_at_trx_commit = 1 # 金融等对数据安全要求极高的场景

# 或
innodb_flush_log_at_trx_commit = 2 # 一般业务场景,OS崩溃时可能丢1秒数据

性能对比

取值 数据安全性 写入TPS 适用场景
0 低(可能丢1秒) 最高 测试环境
1 最高 较低 金融、订单系统
2 中(OS崩溃丢1秒) 较高 一般业务

参数6: innodb_flush_method

控制InnoDB数据文件和日志文件的刷盘方法。

# Linux环境推荐O_DIRECT
# 避免双重缓存(InnoDB缓冲池 + OS Page Cache)
innodb_flush_method = O_DIRECT

# MySQL 8.0默认值
# 如果使用SSD,O_DIRECT是最佳选择

取值说明

方法 数据文件 日志文件 适用场景
fsync 系统默认 系统默认 传统HDD
O_DIRECT 绕过OS缓存 fsync SSD,推荐
O_DIRECT_NO_FSYNC 绕过缓存,无fsync 无fsync 高性能SSD

参数7: innodb_io_capacity

告诉InnoDB后台任务可用的IOPS能力。

# 根据磁盘类型设置
# HDD: 200-800
# SSD: 5000-20000
# NVMe: 20000-50000

innodb_io_capacity = 10000   # 普通SSD
innodb_io_capacity_max = 20000 # 最大值

如何确定正确的值

# 1. 使用fio测试磁盘IOPS
fio --name=randrw --ioengine=libaio --direct=1 --bs=16k 
  --iodepth=64 --rw=randrw --rwmixread=70 --size=1G 
  --runtime=60 --time_based --filename=/var/lib/mysql/fio_test

# 2. 设置io_capacity为测试结果的50-75%
# 3. 设置io_capacity_max为测试结果的100%

参数8: innodb_read_io_threads / innodb_write_io_threads

控制InnoDB后台IO线程数量。

# 默认值都是4
# SSD环境可以适当增加
innodb_read_io_threads = 8
innodb_write_io_threads = 8

# 计算依据:
# 读线程:处理预读和从磁盘读取数据
# 写线程:处理脏页刷盘
# 一般设置为CPU核心数的一半

2.2.2 连接与线程参数(参数9-12)

参数9: max_connections

允许的最大并发连接数。

# 不要设置过大!每个连接都会消耗内存
# 计算公式:预期并发用户数 * 1.5

# 根据应用规模设置
max_connections = 500 # 中小型应用
# max_connections = 2000 # 大型应用

设置过大的危害

-- 每个连接的内存消耗(近似)
-- 基础消耗 + sort_buffer + join_buffer + read_buffer + ...
-- 约 2-10MB per connection

-- 假设max_connections = 10000,sort_buffer = 4MB
-- 最坏情况内存消耗:10000 * 4MB = 40GB
-- 可能导致OOM

合理设置

-- 查看历史最大连接数
SHOWGLOBALSTATUSLIKE'Max_used_connections';
SHOWGLOBALSTATUSLIKE'Max_used_connections_time';

-- 建议设置为历史最大值的1.5-2倍
-- 但不要超过实际需要

参数10: thread_cache_size

线程缓存大小,用于复用已创建的线程。

# 计算公式:max_connections / 10,最大不超过100
thread_cache_size = 50

验证效果

-- 查看线程创建情况
SHOWGLOBALSTATUSLIKE'Threads_%';

-- 线程缓存命中率计算
-- 命中率 = 1 - (Threads_created / Connections)
-- 应该 > 99%

参数11: wait_timeout / interactive_timeout

连接空闲超时时间。

# 非交互连接的超时时间(应用程序连接)
wait_timeout = 600 # 10分钟

# 交互连接的超时时间(mysql客户端)
interactive_timeout = 3600 # 1小时

设置依据

场景 推荐值 说明
Web应用 60-300秒 短连接或连接池
后台服务 600-3600秒 长连接
批处理任务 3600-28800秒 可能长时间运行

参数12: table_open_cache

表文件描述符缓存。

# 计算公式:max_connections * 每个连接平均使用表数
# 一般设置为:max_connections * 2 或更多

table_open_cache = 4000
table_open_cache_instances = 16 # 分成多个实例减少锁竞争

验证效果

-- 查看表缓存状态
SHOWGLOBALSTATUSLIKE'Open%tables%';
SHOWGLOBALSTATUSLIKE'Table_open_cache%';

-- Opened_tables 增长过快说明 table_open_cache 太小

2.2.3 内存相关参数(参数13-16)

参数13: sort_buffer_size

排序缓冲区大小,用于ORDER BY、GROUP BY操作。

# 这是per-session的参数,不要设置太大
# 每个需要排序的查询都会分配一个

sort_buffer_size = 2M # 推荐值
# 最大不要超过8M,否则可能触发swap

常见误区

-- 错误:设置太大
-- sort_buffer_size = 256M # 危险!

-- 假设同时有100个排序查询
-- 内存消耗:100 * 256M = 25.6GB
-- 可能导致OOM或大量swap

参数14: join_buffer_size

连接缓冲区大小,用于没有索引的JOIN操作。

# 同样是per-session参数
join_buffer_size = 2M

# 注意:如果JOIN有索引,这个参数基本不起作用
# 优化的方向应该是添加合适的索引

参数15: tmp_table_size / max_heap_table_size

内存临时表的最大大小。两个参数取较小值生效。

# 两个参数应该设置相同
tmp_table_size = 64M
max_heap_table_size = 64M

验证效果

-- 查看临时表使用情况
SHOWGLOBALSTATUSLIKE'Created_tmp%';

-- 磁盘临时表比例 = Created_tmp_disk_tables / Created_tmp_tables
-- 应该 < 25%,否则需要增大tmp_table_size
-- 或者优化查询,减少临时表使用

参数16: read_buffer_size / read_rnd_buffer_size

顺序读和随机读缓冲区。

# 顺序读缓冲区(全表扫描时使用)
read_buffer_size = 1M

# 随机读缓冲区(ORDER BY时使用)
read_rnd_buffer_size = 1M

# 这两个参数也是per-session的
# 默认值128K-256K对大多数场景足够
# 只有确认有大量全表扫描时才需要增大

2.2.4 日志与复制参数(参数17-20)

参数17: binlog_cache_size

二进制日志缓冲区大小。

# 用于缓存事务的binlog
# 事务过大时会使用临时文件

binlog_cache_size = 4M

# 查看是否需要增大
SHOW GLOBAL STATUS LIKE 'Binlog_cache%';
-- Binlog_cache_disk_use > 0 说明需要增大

参数18: sync_binlog

binlog刷盘策略。

# 0: 依赖OS刷盘(最快,不安全)
# 1: 每次提交都刷盘(最安全,较慢)
# N: 每N个事务刷盘一次

# 生产环境推荐
sync_binlog = 1

# 与 innodb_flush_log_at_trx_commit 配合
# 双1配置(sync_binlog=1, innodb_flush_log_at_trx_commit=1)
# 是最安全的配置,但性能较差

性能与安全的权衡

innodb_flush_log_at_trx_commit sync_binlog 安全性 性能
1 1 最高 最低
2 1 中等
2 100 较高
0 0 最高

参数19: binlog_expire_logs_seconds

binlog自动清理时间(MySQL 8.0+替代expire_logs_days)。

# 保留7天的binlog
binlog_expire_logs_seconds = 604800 # 7 * 24 * 3600

# 考虑因素:
# 1. 从库可能的最大延迟时间
# 2. 数据恢复的时间点需求
# 3. 磁盘空间限制

参数20: replica_parallel_workers(MySQL 8.0.26+)

从库并行复制Worker数量。

# 启用并行复制
replica_parallel_type = LOGICAL_CLOCK
replica_parallel_workers = 16 # CPU核心数的1-2倍
replica_preserve_commit_order = ON

# 主库配合配置
binlog_transaction_dependency_tracking = WRITESET
transaction_write_set_extraction = XXHASH64

2.3 启动和验证

2.3.1 配置文件示例

# /etc/mysql/mysql.conf.d/optimized.cnf
# MySQL 8.0 优化配置模板
# 适用于:64GB内存,NVMe SSD,16核CPU

[mysqld]
# ===================
# 基础配置
# ===================
server_id = 1
port = 3306
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
tmpdir = /tmp

# 字符集
character_set_server = utf8mb4
collation_server = utf8mb4_unicode_ci

# ===================
# InnoDB核心参数
# ===================
# 参数1: 缓冲池 - 64GB * 0.75 ≈ 48GB
innodb_buffer_pool_size = 48G

# 参数2: 缓冲池实例 - 每实例约6GB
innodb_buffer_pool_instances = 8

# 参数3: 重做日志容量 (MySQL 8.0.30+)
innodb_redo_log_capacity = 8G

# 参数4: 日志缓冲区
innodb_log_buffer_size = 64M

# 参数5: 日志刷盘策略
innodb_flush_log_at_trx_commit = 2 # 生产可用1

# 参数6: 刷盘方法
innodb_flush_method = O_DIRECT

# 参数7: IO能力
innodb_io_capacity = 10000
innodb_io_capacity_max = 20000

# 参数8: IO线程
innodb_read_io_threads = 8
innodb_write_io_threads = 8

# InnoDB其他优化
innodb_file_per_table = ON
innodb_stats_on_metadata = OFF
innodb_spin_wait_delay = 6
innodb_lock_wait_timeout = 50
innodb_print_all_deadlocks = ON

# ===================
# 连接与线程参数
# ===================
# 参数9: 最大连接数
max_connections = 500

# 参数10: 线程缓存
thread_cache_size = 50

# 参数11: 连接超时
wait_timeout = 600
interactive_timeout = 3600

# 参数12: 表缓存
table_open_cache = 4000
table_open_cache_instances = 16
table_definition_cache = 2000

# ===================
# 内存相关参数
# ===================
# 参数13: 排序缓冲区
sort_buffer_size = 2M

# 参数14: 连接缓冲区
join_buffer_size = 2M

# 参数15: 临时表大小
tmp_table_size = 64M
max_heap_table_size = 64M

# 参数16: 读缓冲区
read_buffer_size = 1M
read_rnd_buffer_size = 1M

# ===================
# 日志与复制参数
# ===================
# 参数17: binlog缓冲区
binlog_cache_size = 4M

# 参数18: binlog刷盘
sync_binlog = 1

# 参数19: binlog保留
binlog_expire_logs_seconds = 604800

# binlog配置
log_bin = mysql-bin
binlog_format = ROW
binlog_row_image = FULL

# 参数20: 并行复制(从库配置)
# replica_parallel_type = LOGICAL_CLOCK
# replica_parallel_workers = 16
# replica_preserve_commit_order = ON

# ===================
# 日志配置
# ===================
log_error = /var/log/mysql/error.log
slow_query_log = ON
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = ON

# ===================
# 性能Schema
# ===================
performance_schema = ON
performance_schema_instrument = '%=ON'

2.3.2 配置验证脚本

#!/bin/bash
# verify_mysql_config.sh
# MySQL配置验证脚本

MYSQL_USER="root"
MYSQL_PASS="your_password"

echo"=== MySQL配置验证 ==="

# 1. 验证InnoDB缓冲池
echo-e"
[1] InnoDB缓冲池配置"
mysql -u${MYSQL_USER}-p${MYSQL_PASS}-N -e"
SELECT
  CONCAT(ROUND(@@innodb_buffer_pool_size/1024/1024/1024, 1), 'G') AS buffer_pool_size,
  @@innodb_buffer_pool_instances AS instances,
  CONCAT(ROUND(@@innodb_buffer_pool_size/@@innodb_buffer_pool_instances/1024/1024/1024, 2), 'G') AS per_instance
"

# 2. 验证缓冲池命中率
echo-e"
[2] 缓冲池命中率"
mysql -u${MYSQL_USER}-p${MYSQL_PASS}-N -e"
SELECT
  CONCAT(
    ROUND((1 - SUM(CASE WHEN VARIABLE_NAME = 'Innodb_buffer_pool_reads' THEN CAST(VARIABLE_VALUE AS DECIMAL) END) /
       SUM(CASE WHEN VARIABLE_NAME = 'Innodb_buffer_pool_read_requests' THEN CAST(VARIABLE_VALUE AS DECIMAL) END)) * 100, 2),
    '%'
  ) AS hit_rate
FROM performance_schema.global_status
WHERE VARIABLE_NAME IN ('Innodb_buffer_pool_reads', 'Innodb_buffer_pool_read_requests')
"

# 3. 验证连接配置
echo-e"
[3] 连接配置"
mysql -u${MYSQL_USER}-p${MYSQL_PASS}-N -e"
SELECT
  @@max_connections AS max_conn,
  (SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Max_used_connections') AS max_used,
  (SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Threads_connected') AS current
"

# 4. 验证临时表情况
echo-e"
[4] 临时表使用情况"
mysql -u${MYSQL_USER}-p${MYSQL_PASS}-N -e"
SELECT
  (SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Created_tmp_tables') AS tmp_tables,
  (SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Created_tmp_disk_tables') AS disk_tables,
  CONCAT(
    ROUND((SELECT CAST(VARIABLE_VALUE AS DECIMAL) FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Created_tmp_disk_tables') /
       (SELECT CAST(VARIABLE_VALUE AS DECIMAL) FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Created_tmp_tables') * 100, 2),
    '%'
  ) AS disk_pct
"

# 5. 验证IO配置
echo-e"
[5] IO配置"
mysql -u${MYSQL_USER}-p${MYSQL_PASS}-N -e"
SELECT
  @@innodb_io_capacity AS io_capacity,
  @@innodb_io_capacity_max AS io_max,
  @@innodb_read_io_threads AS read_threads,
  @@innodb_write_io_threads AS write_threads
"

echo-e"
验证完成!"

三、示例代码和配置

3.1 完整配置示例

3.1.1 不同规格服务器配置模板

小型服务器(8GB内存,4核CPU)

# /etc/mysql/mysql.conf.d/small.cnf
# 适用于:8GB内存,4核CPU,SSD

[mysqld]
# InnoDB
innodb_buffer_pool_size = 5G
innodb_buffer_pool_instances = 4
innodb_redo_log_capacity = 2G
innodb_log_buffer_size = 16M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
innodb_io_capacity = 2000
innodb_io_capacity_max = 4000
innodb_read_io_threads = 4
innodb_write_io_threads = 4

# 连接
max_connections = 200
thread_cache_size = 20
table_open_cache = 1000

# 内存
sort_buffer_size = 1M
join_buffer_size = 1M
tmp_table_size = 32M
max_heap_table_size = 32M

# 日志
binlog_cache_size = 2M
sync_binlog = 1

中型服务器(32GB内存,8核CPU)

# /etc/mysql/mysql.conf.d/medium.cnf
# 适用于:32GB内存,8核CPU,SSD

[mysqld]
# InnoDB
innodb_buffer_pool_size = 24G
innodb_buffer_pool_instances = 8
innodb_redo_log_capacity = 4G
innodb_log_buffer_size = 32M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
innodb_io_capacity = 5000
innodb_io_capacity_max = 10000
innodb_read_io_threads = 8
innodb_write_io_threads = 8

# 连接
max_connections = 500
thread_cache_size = 50
table_open_cache = 2000

# 内存
sort_buffer_size = 2M
join_buffer_size = 2M
tmp_table_size = 64M
max_heap_table_size = 64M

# 日志
binlog_cache_size = 4M
sync_binlog = 1

大型服务器(128GB内存,32核CPU)

# /etc/mysql/mysql.conf.d/large.cnf
# 适用于:128GB内存,32核CPU,NVMe SSD

[mysqld]
# InnoDB
innodb_buffer_pool_size = 96G
innodb_buffer_pool_instances = 16
innodb_redo_log_capacity = 16G
innodb_log_buffer_size = 128M
innodb_flush_log_at_trx_commit = 1 # 大型系统通常对数据安全要求高
innodb_flush_method = O_DIRECT
innodb_io_capacity = 20000
innodb_io_capacity_max = 40000
innodb_read_io_threads = 16
innodb_write_io_threads = 16

# 连接
max_connections = 2000
thread_cache_size = 100
table_open_cache = 8000
table_open_cache_instances = 32

# 内存
sort_buffer_size = 4M
join_buffer_size = 4M
tmp_table_size = 128M
max_heap_table_size = 128M

# 日志
binlog_cache_size = 8M
sync_binlog = 1

# 其他优化
innodb_page_cleaners = 8
innodb_purge_threads = 8
innodb_lru_scan_depth = 2048

3.1.2 动态参数调整脚本

#!/usr/bin/env python3
# dynamic_tuning.py
# MySQL动态参数调优脚本

importpymysql
fromdataclassesimportdataclass
fromtypingimportDict, List, Tuple
importlogging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


@dataclass
classTuningRecommendation:
 """调优建议"""
  parameter: str
  current_value: str
  recommended_value: str
  reason: str
  is_dynamic: bool


classMySQLTuningAdvisor:
 """MySQL调优顾问"""

 def__init__(self, host: str, user: str, password: str, port: int =3306):
    self.connection = pymysql.connect(
      host=host,
      user=user,
      password=password,
      port=port,
      cursorclass=pymysql.cursors.DictCursor
    )

 defanalyze(self)-> List[TuningRecommendation]:
   """分析并生成调优建议"""
    recommendations = []

   # 分析各项指标
    recommendations.extend(self._analyze_buffer_pool())
    recommendations.extend(self._analyze_connections())
    recommendations.extend(self._analyze_temp_tables())
    recommendations.extend(self._analyze_threads())
    recommendations.extend(self._analyze_io())

   returnrecommendations

 def_get_variable(self, name: str)-> str:
   """获取变量值"""
   withself.connection.cursor()ascursor:
      cursor.execute(f"SHOW VARIABLES LIKE '{name}'")
      result = cursor.fetchone()
     returnresult['Value']ifresultelseNone

 def_get_status(self, name: str)-> int:
   """获取状态值"""
   withself.connection.cursor()ascursor:
      cursor.execute(f"SHOW GLOBAL STATUS LIKE '{name}'")
      result = cursor.fetchone()
     returnint(result['Value'])ifresultelse0

 def_analyze_buffer_pool(self)-> List[TuningRecommendation]:
   """分析缓冲池"""
    recommendations = []

    reads = self._get_status('Innodb_buffer_pool_reads')
    read_requests = self._get_status('Innodb_buffer_pool_read_requests')

   ifread_requests >0:
      hit_rate = (1- reads / read_requests) *100

     ifhit_rate < 99:
                current_size = int(self._get_variable('innodb_buffer_pool_size'))
                recommended_size = int(current_size * 1.5)

                recommendations.append(TuningRecommendation(
                    parameter='innodb_buffer_pool_size',
                    current_value=self._format_bytes(current_size),
                    recommended_value=self._format_bytes(recommended_size),
                    reason=f'缓冲池命中率 {hit_rate:.2f}% 低于99%',
                    is_dynamic=True# MySQL 8.0支持动态调整
                ))

        return recommendations

    def _analyze_connections(self) -> List[TuningRecommendation]:
   """分析连接数"""
    recommendations = []

    max_conn = int(self._get_variable('max_connections'))
    max_used = self._get_status('Max_used_connections')
    usage_rate = max_used / max_conn *100

   ifusage_rate >80:
      recommendations.append(TuningRecommendation(
        parameter='max_connections',
        current_value=str(max_conn),
        recommended_value=str(int(max_used *1.5)),
        reason=f'连接使用率{usage_rate:.1f}% 超过80%',
        is_dynamic=True
      ))
   elifusage_rate < 20and max_conn >200:
      recommendations.append(TuningRecommendation(
        parameter='max_connections',
        current_value=str(max_conn),
        recommended_value=str(max(200, int(max_used *2))),
        reason=f'连接使用率仅{usage_rate:.1f}%,max_connections设置过大',
        is_dynamic=True
      ))

   returnrecommendations

 def_analyze_temp_tables(self)-> List[TuningRecommendation]:
   """分析临时表"""
    recommendations = []

    tmp_tables = self._get_status('Created_tmp_tables')
    tmp_disk_tables = self._get_status('Created_tmp_disk_tables')

   iftmp_tables >0:
      disk_ratio = tmp_disk_tables / tmp_tables *100

     ifdisk_ratio >25:
        current_size = int(self._get_variable('tmp_table_size'))
        recommended_size = min(current_size *2,256*1024*1024) # 最大256MB

        recommendations.append(TuningRecommendation(
          parameter='tmp_table_size',
          current_value=self._format_bytes(current_size),
          recommended_value=self._format_bytes(recommended_size),
          reason=f'磁盘临时表比例{disk_ratio:.1f}% 超过25%',
          is_dynamic=True
        ))

   returnrecommendations

 def_analyze_threads(self)-> List[TuningRecommendation]:
   """分析线程缓存"""
    recommendations = []

    threads_created = self._get_status('Threads_created')
    connections = self._get_status('Connections')

   ifconnections >0:
      thread_cache_hit_rate = (1- threads_created / connections) *100

     ifthread_cache_hit_rate < 99:
                current_cache = int(self._get_variable('thread_cache_size'))
                recommendations.append(TuningRecommendation(
                    parameter='thread_cache_size',
                    current_value=str(current_cache),
                    recommended_value=str(min(current_cache + 20, 100)),
                    reason=f'线程缓存命中率 {thread_cache_hit_rate:.1f}% 低于99%',
                    is_dynamic=True
                ))

        return recommendations

    def _analyze_io(self) -> List[TuningRecommendation]:
   """分析IO配置"""
    recommendations = []

   # 检查日志等待
    log_waits = self._get_status('Innodb_log_waits')
   iflog_waits >0:
      current_size = int(self._get_variable('innodb_log_buffer_size'))
      recommendations.append(TuningRecommendation(
        parameter='innodb_log_buffer_size',
        current_value=self._format_bytes(current_size),
        recommended_value=self._format_bytes(current_size *2),
        reason=f'日志缓冲区等待次数{log_waits}',
        is_dynamic=False# 需要重启
      ))

   returnrecommendations

  @staticmethod
 def_format_bytes(size: int)-> str:
   """格式化字节数"""
   forunitin['B','K','M','G']:
     ifsize < 1024:
                returnf"{size}{unit}"
            size //= 1024
        returnf"{size}T"

    def apply_recommendations(
        self,
        recommendations: List[TuningRecommendation],
        dynamic_only: bool = True
    ) -> Dict[str, bool]:
   """应用调优建议"""
    results = {}

   forrecinrecommendations:
     ifdynamic_onlyandnotrec.is_dynamic:
        logger.info(f"跳过非动态参数:{rec.parameter}")
        results[rec.parameter] =False
       continue

     try:
       withself.connection.cursor()ascursor:
          cursor.execute(
           f"SET GLOBAL{rec.parameter}={rec.recommended_value}"
          )
          self.connection.commit()
          logger.info(
           f"成功调整{rec.parameter}: "
           f"{rec.current_value}->{rec.recommended_value}"
          )
          results[rec.parameter] =True
     exceptExceptionase:
        logger.error(f"调整{rec.parameter}失败:{e}")
        results[rec.parameter] =False

   returnresults

 defgenerate_report(self, recommendations: List[TuningRecommendation])-> str:
   """生成调优报告"""
    report = []
    report.append("="*60)
    report.append("MySQL参数调优建议报告")
    report.append("="*60)

   ifnotrecommendations:
      report.append("当前配置良好,无需调整")
   else:
      report.append(f"发现{len(recommendations)}项调优建议:
")

      dynamic_params = [rforrinrecommendationsifr.is_dynamic]
      static_params = [rforrinrecommendationsifnotr.is_dynamic]

     ifdynamic_params:
        report.append("【可动态调整的参数】")
       fori, recinenumerate(dynamic_params,1):
          report.append(f"
{i}.{rec.parameter}")
          report.append(f"  当前值:{rec.current_value}")
          report.append(f"  建议值:{rec.recommended_value}")
          report.append(f"  原因:{rec.reason}")

     ifstatic_params:
        report.append("
【需要重启生效的参数】")
       fori, recinenumerate(static_params,1):
          report.append(f"
{i}.{rec.parameter}")
          report.append(f"  当前值:{rec.current_value}")
          report.append(f"  建议值:{rec.recommended_value}")
          report.append(f"  原因:{rec.reason}")

   return"
".join(report)


if__name__ =="__main__":
  advisor = MySQLTuningAdvisor(
    host="127.0.0.1",
    user="root",
    password="your_password"
  )

  recommendations = advisor.analyze()
  report = advisor.generate_report(recommendations)
  print(report)

 # 可选:应用动态参数调整
 # results = advisor.apply_recommendations(recommendations, dynamic_only=True)

3.2 实际应用案例

3.2.1 案例一:电商大促前的参数调优

场景描述

某电商平台即将迎来双11大促,预计流量是平时的20倍。当前配置是根据日常负载设置的,需要针对大促场景进行调优。

当前配置

# 日常配置
innodb_buffer_pool_size = 24G
max_connections = 500
innodb_io_capacity = 2000
sync_binlog = 1
innodb_flush_log_at_trx_commit = 1

优化方案

# 大促期间配置

# 1. 增大缓冲池应对更多并发读取
innodb_buffer_pool_size = 48G # 从24G增加到48G

# 2. 增大连接数
max_connections = 2000 # 从500增加到2000

# 3. 提升IO能力
innodb_io_capacity = 10000 # 从2000增加到10000
innodb_io_capacity_max = 20000

# 4. 牺牲少量安全性换取性能
sync_binlog = 100 # 从1改为100
innodb_flush_log_at_trx_commit = 2 # 从1改为2

# 5. 增大临时表大小应对复杂查询
tmp_table_size = 128M
max_heap_table_size = 128M

# 6. 增大排序缓冲区
sort_buffer_size = 4M
join_buffer_size = 4M

动态调整脚本

#!/bin/bash
# promotion_tuning.sh
# 大促参数切换脚本

MYSQL_CMD="mysql -u root -p'password'"

echo"开始应用大促配置..."

# 动态调整参数
$MYSQL_CMD<< EOF
-- 增大连接数
SET GLOBAL max_connections = 2000;

-- 调整IO参数
SET GLOBAL innodb_io_capacity = 10000;
SET GLOBAL innodb_io_capacity_max = 20000;

-- 放宽刷盘策略
SET GLOBAL sync_binlog = 100;
SET GLOBAL innodb_flush_log_at_trx_commit = 2;

-- 增大会话缓冲区
SET GLOBAL sort_buffer_size = 4*1024*1024;
SET GLOBAL join_buffer_size = 4*1024*1024;
SET GLOBAL tmp_table_size = 128*1024*1024;
SET GLOBAL max_heap_table_size = 128*1024*1024;

-- 验证
SHOW VARIABLES LIKE 'max_connections';
SHOW VARIABLES LIKE 'innodb_io_capacity';
SHOW VARIABLES LIKE 'sync_binlog';
SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';
EOF

echo"大促配置应用完成!"
echo"注意:innodb_buffer_pool_size需要在线扩容或重启"

大促后恢复

#!/bin/bash
# restore_normal.sh
# 恢复日常配置

MYSQL_CMD="mysql -u root -p'password'"

echo"恢复日常配置..."

$MYSQL_CMD<< EOF
SET GLOBAL max_connections = 500;
SET GLOBAL innodb_io_capacity = 2000;
SET GLOBAL innodb_io_capacity_max = 4000;
SET GLOBAL sync_binlog = 1;
SET GLOBAL innodb_flush_log_at_trx_commit = 1;
SET GLOBAL sort_buffer_size = 2*1024*1024;
SET GLOBAL join_buffer_size = 2*1024*1024;
SET GLOBAL tmp_table_size = 64*1024*1024;
SET GLOBAL max_heap_table_size = 64*1024*1024;
EOF

echo"日常配置恢复完成!"

3.2.2 案例二:慢查询导致的性能问题排查

问题现象

数据库CPU持续在80%以上,慢查询数量增加,业务响应变慢。

排查步骤

-- 1. 查看当前运行的查询
SELECT
 id,
 user,
  host,
  db,
  command,
 time,
  state,
 LEFT(info,100)ASquery
FROMinformation_schema.processlist
WHEREcommand !='Sleep'
ORDERBYtimeDESC;

-- 2. 分析慢查询日志
-- 使用pt-query-digest分析

-- 3. 查看资源消耗最高的语句
SELECT
  DIGEST_TEXT,
  COUNT_STARASexec_count,
  SUM_TIMER_WAIT/1000000000000AStotal_sec,
  AVG_TIMER_WAIT/1000000000ASavg_ms,
  SUM_ROWS_EXAMINEDASrows_examined
FROMperformance_schema.events_statements_summary_by_digest
ORDERBYSUM_TIMER_WAITDESC
LIMIT10;

发现问题

-- 发现大量全表扫描查询
SELECT*FROMordersWHEREstatus='pending'
-- 该表有500万行,status字段没有索引

优化方案

-- 1. 添加索引
CREATEINDEXidx_statusONorders(status);

-- 2. 临时增大sort_buffer_size应对积压
SETGLOBALsort_buffer_size =8*1024*1024;

-- 3. 增大read_buffer_size缓解全表扫描
SETGLOBALread_buffer_size =2*1024*1024;

参数调优建议

# 针对读多写少场景
read_buffer_size = 2M
read_rnd_buffer_size = 2M

# 针对复杂查询场景
sort_buffer_size = 4M
join_buffer_size = 4M
tmp_table_size = 128M
max_heap_table_size = 128M

3.2.3 案例三:从库延迟优化

问题现象

从库复制延迟持续在几百秒,影响读写分离架构。

排查命令

-- 查看从库状态
SHOWREPLICASTATUSG

-- 关键指标
-- Seconds_Behind_Source: 延迟秒数
-- Relay_Log_Space: 中继日志大小
-- Replica_SQL_Running_State: SQL线程状态

发现问题

从库使用单线程复制,无法充分利用多核CPU。

优化方案

-- 停止复制
STOPREPLICA;

-- 配置并行复制
SETGLOBALreplica_parallel_type ='LOGICAL_CLOCK';
SETGLOBALreplica_parallel_workers =16;
SETGLOBALreplica_preserve_commit_order =ON;

-- 启动复制
STARTREPLICA;

从库专用配置

# /etc/mysql/mysql.conf.d/replica.cnf
# 从库专用优化配置

[mysqld]
# 并行复制
replica_parallel_type = LOGICAL_CLOCK
replica_parallel_workers = 16
replica_preserve_commit_order = ON

# 从库可以放宽刷盘策略
innodb_flush_log_at_trx_commit = 2
sync_binlog = 0

# 增大IO能力加快回放
innodb_io_capacity = 15000
innodb_io_capacity_max = 30000

# 从库不需要二进制日志(除非级联复制)
# skip_log_bin

# 只读
read_only = ON
super_read_only = ON

四、最佳实践和注意事项

4.1 最佳实践

4.1.1 参数调优黄金法则

法则1:先测量后调优

# 使用sysbench进行基准测试
sysbench oltp_read_write 
  --mysql-host=127.0.0.1 
  --mysql-user=test
  --mysql-password=test
  --mysql-db=sbtest 
  --tables=10 
  --table-size=1000000 
  --threads=32 
  --time=300 
  --report-interval=10 
  prepare

sysbench oltp_read_write 
  --mysql-host=127.0.0.1 
  --mysql-user=test
  --mysql-password=test
  --mysql-db=sbtest 
  --tables=10 
  --table-size=1000000 
  --threads=32 
  --time=300 
  --report-interval=10 
  run

法则2:单参数调整

每次只调整一个参数,观察效果后再调整下一个。

法则3:记录所有变更

-- 创建参数变更记录表
CREATETABLEparam_change_log (
 idINTPRIMARYKEYAUTO_INCREMENT,
  changed_atTIMESTAMPDEFAULTCURRENT_TIMESTAMP,
  parameterVARCHAR(100),
  old_valueVARCHAR(100),
  new_valueVARCHAR(100),
  changed_byVARCHAR(50),
  reasonVARCHAR(500)
);

-- 记录变更
INSERTINTOparam_change_log (parameter, old_value, new_value, changed_by, reason)
VALUES('innodb_buffer_pool_size','24G','48G','dba_john','大促扩容');

4.1.2 内存参数配置原则

总可用内存 = 物理内存 * 90%(留10%给OS)

内存分配 =
 innodb_buffer_pool_size (60-70%)
 + max_connections * per_connection_memory (10-20%)
 + 其他缓冲区 (5-10%)
 + OS和其他进程 (10%)

per_connection_memory计算

-- 每个连接的最大内存消耗
SELECT
  (@@sort_buffer_size + @@join_buffer_size + @@read_buffer_size +
  @@read_rnd_buffer_size + @@binlog_cache_size) /1024/1024ASper_conn_mb;

-- 最坏情况总消耗
SELECT
  @@max_connections *
  (@@sort_buffer_size + @@join_buffer_size + @@read_buffer_size +
  @@read_rnd_buffer_size + @@binlog_cache_size) /1024/1024/1024ASmax_session_memory_gb;

4.1.3 IO参数配置原则

存储类型 innodb_io_capacity innodb_io_capacity_max
HDD 7200RPM 200 400
HDD 15000RPM 400-800 1000
SSD SATA 2000-5000 5000-10000
SSD NVMe 10000-50000 20000-100000
云盘SSD 根据规格 根据规格

4.2 注意事项

4.2.1 常见错误

错误配置 问题 正确做法
innodb_buffer_pool_size = 物理内存 OOM 设为物理内存的70-80%
max_connections = 10000 内存耗尽 根据实际需要设置
sort_buffer_size = 256M 单会话内存过大 设为1-4M
innodb_log_file_size太小 频繁checkpoint 设为能容纳1小时日志量
sync_binlog = 0 (生产) 数据丢失风险 生产环境设为1

4.2.2 需要重启的参数

以下参数修改后需要重启MySQL:

# 需要重启的参数
innodb_buffer_pool_size    # MySQL 8.0可在线调整
innodb_log_file_size      # 8.0.30前需要重启
innodb_page_size        # 初始化后无法修改
innodb_data_file_path     # 无法在线修改
lower_case_table_names     # 无法在线修改

4.2.3 动态参数调整注意事项

-- 在线调整buffer_pool_size(MySQL 8.0)
-- 可能需要几分钟完成

SETGLOBALinnodb_buffer_pool_size =48*1024*1024*1024;

-- 查看调整进度
SHOWSTATUSLIKE'Innodb_buffer_pool_resize_status';

五、故障排查和监控

5.1 参数相关问题诊断

-- 内存不足诊断
SELECT
 CONCAT(ROUND(@@innodb_buffer_pool_size/1024/1024/1024,1),'G')ASbuffer_pool,
 CONCAT(@@max_connections,' * ',
     ROUND((@@sort_buffer_size + @@join_buffer_size)/1024/1024,1),'M = ',
     ROUND(@@max_connections * (@@sort_buffer_size + @@join_buffer_size)/1024/1024/1024,1),'G'
  )ASmax_session_memory;

-- 连接数问题诊断
SELECT
  @@max_connectionsASmax_conn,
  (SELECTVARIABLE_VALUEFROMperformance_schema.global_status
  WHEREVARIABLE_NAME ='Max_used_connections')ASmax_used,
  (SELECTVARIABLE_VALUEFROMperformance_schema.global_status
  WHEREVARIABLE_NAME ='Threads_connected')AScurrent,
  (SELECTVARIABLE_VALUEFROMperformance_schema.global_status
  WHEREVARIABLE_NAME ='Aborted_connects')ASaborted;

5.2 关键监控指标

指标 健康阈值 查询方法
缓冲池命中率 > 99% Innodb_buffer_pool_read_requests vs reads
连接使用率 < 80% Threads_connected / max_connections
临时表磁盘率 < 25% Created_tmp_disk_tables / Created_tmp_tables
线程缓存命中率 > 99% 1 - Threads_created / Connections
表缓存命中率 > 99% 1 - Opened_tables / Open_tables

5.3 监控脚本

#!/bin/bash
# mysql_parameter_monitor.sh
# MySQL参数效果监控脚本

MYSQL_CMD="mysql -u monitor -p'password' -N"

whiletrue;do
  timestamp=$(date'+%Y-%m-%d %H:%M:%S')

 # 收集指标
  result=$($MYSQL_CMD<< EOF
SELECT
    ROUND((1 - bp_reads.val / bp_requests.val) * 100, 2) AS buffer_hit_rate,
    ROUND(threads.val / max_conn.val * 100, 1) AS conn_usage,
    ROUND(disk_tmp.val / all_tmp.val * 100, 1) AS disk_tmp_pct
FROM
    (SELECT CAST(VARIABLE_VALUE AS DECIMAL) AS val FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Innodb_buffer_pool_reads') bp_reads,
    (SELECT CAST(VARIABLE_VALUE AS DECIMAL) AS val FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Innodb_buffer_pool_read_requests') bp_requests,
    (SELECT CAST(VARIABLE_VALUE AS DECIMAL) AS val FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Threads_connected') threads,
    (SELECT CAST(VARIABLE_VALUE AS DECIMAL) AS val FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'max_connections') max_conn,
    (SELECT CAST(VARIABLE_VALUE AS DECIMAL) AS val FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Created_tmp_disk_tables') disk_tmp,
    (SELECT CAST(VARIABLE_VALUE AS DECIMAL) AS val FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Created_tmp_tables') all_tmp;
EOF
)

    echo"$timestamp | $result"
    sleep 60
done

六、总结

6.1 技术要点回顾

本文详细介绍了MySQL 20个核心参数的调优方法,关键要点如下:

innodb_buffer_pool_size是最重要的参数

设置为物理内存的70-80%

命中率应保持在99%以上

连接相关参数要平衡

max_connections不是越大越好

每个连接都会消耗内存

IO参数要匹配硬件能力

innodb_io_capacity根据磁盘类型设置

SSD和HDD差异巨大

刷盘策略要权衡安全与性能

双1配置最安全但性能较差

根据业务重要性选择合适配置

并行复制大幅提升从库性能

MySQL 8.0的LOGICAL_CLOCK配合WRITESET

Worker数量设置为CPU核心数的1-2倍

6.2 20个参数速查表

序号 参数 推荐值 说明
1 innodb_buffer_pool_size 物理内存70-80% 最重要的参数
2 innodb_buffer_pool_instances 8-16 减少锁竞争
3 innodb_redo_log_capacity 4-8G 8.0.30+新参数
4 innodb_log_buffer_size 64M 日志缓冲区
5 innodb_flush_log_at_trx_commit 1或2 刷盘策略
6 innodb_flush_method O_DIRECT SSD推荐
7 innodb_io_capacity 根据磁盘 IO能力
8 innodb_read/write_io_threads 8 IO线程
9 max_connections 根据需要 最大连接
10 thread_cache_size 50 线程缓存
11 wait_timeout 600 空闲超时
12 table_open_cache 4000 表缓存
13 sort_buffer_size 2M 排序缓冲
14 join_buffer_size 2M 连接缓冲
15 tmp_table_size 64M 临时表
16 read_buffer_size 1M 读缓冲
17 binlog_cache_size 4M binlog缓冲
18 sync_binlog 1 binlog刷盘
19 binlog_expire_logs_seconds 604800 binlog保留
20 replica_parallel_workers 16 并行复制

6.3 参考资料

MySQL 8.0 Reference Manual - Server System Variables https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html

High Performance MySQL, 4th Edition - O'Reilly

MySQL Performance Blog - Percona https://www.percona.com/blog/

MySQL Server Team Blog https://dev.mysql.com/blog-archive/

附录

A. 命令速查表

-- 查看所有变量
SHOWVARIABLES;
SHOWGLOBALVARIABLESLIKE'%innodb%';

-- 查看所有状态
SHOWGLOBALSTATUS;
SHOWGLOBALSTATUSLIKE'%Innodb%';

-- 动态修改参数
SETGLOBALvariable_name =value;
SETSESSIONvariable_name =value;

-- 查看参数是否可动态修改
SELECT*FROMperformance_schema.global_variables
WHEREVARIABLE_NAME ='innodb_buffer_pool_size';

B. 配置参数快速对照

场景 关键参数调整
读多写少 增大buffer_pool,减小redo_log
写多读少 增大redo_log,调整刷盘策略
复杂查询 增大tmp_table_size,sort_buffer
高并发 增大connections,thread_cache
从库延迟 parallel_workers,放宽刷盘

C. 术语表

术语 说明
Buffer Pool InnoDB缓冲池,缓存数据和索引
Redo Log 重做日志,保证事务持久性
Checkpoint 检查点,将脏页刷盘的操作
IOPS 每秒IO操作数
TPS 每秒事务数
QPS 每秒查询数

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 服务器
    +关注

    关注

    14

    文章

    10440

    浏览量

    91849
  • 内存
    +关注

    关注

    9

    文章

    3255

    浏览量

    76591
  • MySQL
    +关注

    关注

    1

    文章

    938

    浏览量

    29851

原文标题:MySQL参数调优实战:20个关键参数的最佳配置

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    MySQL的安装和配置教程手册

    ;quot;Verdana">MySQL的安装和配置教程手册</font></font><br
    发表于 09-27 23:13

    0基础学Mysql:mysql入门视频教程!

    互联网行业的高速发展,各个中小企业的数据库存放的数据,也已经达到了一个相当高的数量级。学习目标:深入理解MySQL数据库的原理从硬件 系统 MySQL参数 执行计划 SQL优化等多角度学习My
    发表于 07-08 10:51

    Mysql优化选择最佳索引规则

    索引的目的在于提高查询效率,其功能可类比字典,通过该索引可以查询到我们想要查询的信息,因此,选择建立好的索引十分重要,以下是为Mysql优化选择最佳索引的方法步骤:1. 首先列出查询中所有使用的表
    发表于 07-06 15:13

    MySQL的几种复制配置

    MySQL主从复制、主主复制、双主多从配置
    发表于 04-16 09:50

    MySql5.6性能优化最佳实践

    MySql5.6性能优化最佳实践
    发表于 09-08 08:47 13次下载
    <b class='flag-5'>MySql</b>5.6性能优化<b class='flag-5'>最佳</b>实践

    利用Mycat实现MySQL读写分离、分库分表最佳实践

    利用Mycat实现MySQL读写分离、分库分表最佳实践
    发表于 09-08 10:20 14次下载
    利用Mycat实现<b class='flag-5'>MySQL</b>读写分离、分库分表<b class='flag-5'>最佳</b>实践

    MySQL 集群最佳解决方案

    MySQL 集群最佳解决方案
    发表于 09-09 08:40 10次下载
    <b class='flag-5'>MySQL</b> 集群<b class='flag-5'>最佳</b>解决方案

    MySQL安装说明及配置

    本文档为C/C++学习指南(MySQL 篇)的官方文档,本文介绍的 Windows 上安装 MySQL 5.5 服务器的方法,以及安装后的配置
    发表于 09-11 16:54 5次下载
    <b class='flag-5'>MySQL</b>安装说明及<b class='flag-5'>配置</b>

    保护MySQL数据仓库的最佳实践

    数据仓库中最常见的数据库管理系统可能就是开源的MySQL数据库。以下5个小技巧重点介绍了一些保护MySQL数据仓库的最佳实践。 1.限制访问 确保MySQL数据仓库安全最有效的方法之一
    发表于 09-27 14:10 0次下载

    虚拟机:为icescrum 配置MySQL

    虚拟机:为icescrum 配置MySQL
    的头像 发表于 06-22 16:57 2759次阅读
    虚拟机:为icescrum <b class='flag-5'>配置</b><b class='flag-5'>MySQL</b>

    CentOS下配置Apache+PHP+MySQL

    CentOS下配置Apache+PHP+MySQL(开关电源技术课程设计buckboost)-文档为CentOS下配置Apache+PHP+MySQL详解文档,是一份不错的参考资料,感
    发表于 09-18 15:10 11次下载
    CentOS下<b class='flag-5'>配置</b>Apache+PHP+<b class='flag-5'>MySQL</b>

    设计动态网站的最佳方案-Apache+PHP+MySQL

    设计动态网站的最佳方案-Apache+PHP+MySQL(电源技术是sci吗)-文档为设计动态网站的最佳方案-Apache+PHP+MySQL总结文档,是一份不错的参考资料,感兴趣的可
    发表于 09-18 17:53 9次下载
    设计动态网站的<b class='flag-5'>最佳</b>方案-Apache+PHP+<b class='flag-5'>MySQL</b>

    mysql配置失败怎么办

    MySQL是一款广泛使用的关系型数据库管理系统,但在配置过程中可能会出现各种问题,导致配置失败。本文将详细介绍MySQL配置失败的常见原因和
    的头像 发表于 12-06 11:03 4884次阅读

    配置MySQL主从复制和读写分离

    配置MySQL主从复制和读写分离
    的头像 发表于 10-23 11:44 1347次阅读
    <b class='flag-5'>配置</b><b class='flag-5'>MySQL</b>主从复制和读写分离

    高手支招:彻底解决MySQL数据库环境配置难题

    其实MySQL环境配置并无难点,核心在于掌握版本选择、权限路径、端口编码这三大关键,避开常见陷阱,按步骤操作并做好验证。
    的头像 发表于 03-13 11:38 270次阅读