MySQL 8.0生产调优完全指南:香港服务器参数优化 + 慢查询 + 连接池实战

MySQL 8.0生产调优完全指南:香港服务器参数优化 + 慢查询 + 连接池实战

MySQL 默认配置为通用场景设计,在香港生产服务器上直接运行几乎必然遇到性能瓶颈。本文系统覆盖 MySQL 8.0 的生产调优,从内存分配到连接池,从慢查询到执行计划分析,提供一套可直接应用于生产环境的配置方案。


一、核心参数调优(my.cnf)

<code"># /etc/mysql/mysql.conf.d/production.cnf
[mysqld]

# ══ 内存配置(最关键)══

# InnoDB Buffer Pool:缓存数据和索引(数据库最重要的内存区域)
# 规则:总内存的 60~70%(数据库专用服务器可达 80%)
# 8G 服务器:5~6GB
innodb_buffer_pool_size = 5G

# Buffer Pool 分块(每块约 1GB,减少内存分配时的锁竞争)
innodb_buffer_pool_instances = 5   # 与 innodb_buffer_pool_size GB 数相同

# Query Cache(MySQL 8.0 已删除,无需配置)

# 每个连接的排序/哈希缓冲区
sort_buffer_size = 2M              # 排序操作(ORDER BY)
join_buffer_size = 2M              # 无索引 JOIN 操作
read_buffer_size = 1M              # 全表扫描缓冲
read_rnd_buffer_size = 4M         # 随机读取缓冲(ORDER BY 后读取)
tmp_table_size = 64M              # 内存临时表上限(超出转磁盘)
max_heap_table_size = 64M

# ══ InnoDB I/O 配置 ══

# Redo Log 大小(影响崩溃恢复速度和写入性能)
# MySQL 8.0.30+ 自动管理,无需手动设置
# innodb_log_file_size = 1G      # 仅 8.0.30 以前需要配置

# I/O 能力(告知 MySQL 磁盘性能,影响刷新策略)
# SSD:根据实际 IOPS 设置(fio 测试)
innodb_io_capacity = 2000          # SSD 约 2000~10000
innodb_io_capacity_max = 4000

# Flush 策略(SSD 推荐 O_DIRECT,绕过系统文件缓存避免双缓冲)
innodb_flush_method = O_DIRECT

# Doublewrite Buffer(防止页撕裂,SSD 可考虑关闭提升性能)
innodb_doublewrite = ON

# ══ 连接配置 ══
max_connections = 500              # 根据 RAM 计算:RAM(MB) / 每连接内存(MB)
thread_cache_size = 50             # 线程缓存(减少创建/销毁线程开销)
wait_timeout = 600                 # 空闲连接超时(10分钟)
interactive_timeout = 600

# ══ 日志配置 ══
slow_query_log = ON
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 0.5              # 超过500ms的查询记录
log_queries_not_using_indexes = ON # 记录未用索引的查询
min_examined_row_limit = 1000     # 扫描行数少于1000的查询不记录

# Binlog(主从复制和时间点恢复必须开启)
log_bin = /var/log/mysql/mysql-bin
binlog_format = ROW                # 推荐 ROW 格式,最安全
binlog_expire_logs_seconds = 604800  # 7天后自动清理 binlog
max_binlog_size = 1G

# ══ 字符集 ══
character-set-server = utf8mb4
collation-server = utf8mb4_0900_ai_ci

二、ProxySQL 连接池配置

<code"># 安装 ProxySQL(提供连接池 + 读写分离 + 查询路由)
apt install -y proxysql

# /etc/proxysql.cnf 基础配置
datadir="/var/lib/proxysql"
admin_variables=
{
    admin_credentials="admin:ProxySQLAdmin2026"
    mysql_ifaces="0.0.0.0:6032"     # ProxySQL 管理端口
}
mysql_variables=
{
    threads=4
    max_connections=2048
    default_query_delay=0
    default_query_timeout=36000000
    poll_timeout=2000
    interfaces="0.0.0.0:6033"       # 应用连接 ProxySQL 的端口
    default_schema="information_schema"
    stacksize=1048576
    server_version="8.0.30"
    connect_timeout_server=3000
    monitor_username="monitor"
    monitor_password="MonitorPass2026"
}

# 启动后通过 MySQL 客户端管理 ProxySQL
mysql -u admin -pProxySQLAdmin2026 -h 127.0.0.1 -P 6032

-- 添加后端 MySQL 服务器
INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES
  (1, '127.0.0.1', 3306),   -- 主库(hostgroup 1 = 写)
  (2, '10.0.0.2', 3306),    -- 从库1(hostgroup 2 = 读)
  (2, '10.0.0.3', 3306);    -- 从库2

-- 读写分离规则
INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply) VALUES
  (1, 1, '^SELECT.*FOR UPDATE', 1, 1),  -- SELECT FOR UPDATE → 主库
  (2, 1, '^SELECT', 2, 1);              -- 普通 SELECT → 从库

LOAD MYSQL SERVERS TO RUNTIME;
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
SAVE MYSQL QUERY RULES TO DISK;

三、慢查询分析

<code"># 使用 pt-query-digest 分析慢查询日志(Percona Toolkit)
apt install -y percona-toolkit

pt-query-digest /var/log/mysql/slow.log | head -100

# 输出示例:
# # Profile
# # Rank Query ID                      Response time  Calls  R/Call  Item
# # ==== ============================= ============== ====== ======= ====
# #    1 0xABC123...                    45.2380 23.6%    1421  0.0318  SELECT orders
# #    2 0xDEF456...                    38.1020 19.9%     892  0.0427  SELECT products

# 查看最慢的查询详情(包含完整 SQL 和统计信息)
pt-query-digest /var/log/mysql/slow.log \
  --limit 5 \
  --report-format query_report

四、EXPLAIN 执行计划分析

<code">-- 分析查询执行计划
EXPLAIN FORMAT=JSON
SELECT o.id, o.status, c.email
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE o.status = 'pending'
  AND o.created_at > '2026-01-01'
ORDER BY o.created_at DESC
LIMIT 20;

-- 关键字段解读:
-- type: ALL(全表扫描,危险)→ 需要添加索引
-- type: ref(索引范围,良好)
-- type: const(主键查找,最快)
-- rows: 执行计划估算的扫描行数(越大越慢)
-- Extra: Using filesort(需要额外排序,可能慢)
-- Extra: Using index(覆盖索引,很快)

-- 添加合适的复合索引
CREATE INDEX idx_orders_status_date ON orders (status, created_at DESC);

-- 再次 EXPLAIN,确认 type 从 ALL 变为 range
EXPLAIN SELECT ... ;

五、MySQL 8.0 新特性应用

<code">-- ── 窗口函数(替代复杂子查询)──
-- 每个用户的订单排名(按金额降序)
SELECT
    user_id,
    order_id,
    amount,
    RANK() OVER (PARTITION BY user_id ORDER BY amount DESC) AS rank_in_user,
    SUM(amount) OVER (PARTITION BY user_id) AS user_total
FROM orders;

-- ── JSON 函数(处理 JSON 列)──
-- 从 JSON 列提取数据并建立虚拟列+索引
ALTER TABLE products
  ADD COLUMN price_usd DECIMAL(10,2) GENERATED ALWAYS AS
    (JSON_UNQUOTE(attributes->'$.price_usd')) STORED,
  ADD INDEX idx_price_usd (price_usd);

-- 现在可以高效查询 JSON 中的价格字段
SELECT * FROM products WHERE price_usd BETWEEN 10 AND 50;

-- ── Clone Plugin(在线克隆数据库到新实例)──
INSTALL PLUGIN clone SONAME 'mysql_clone.so';
-- 将当前数据库克隆到远程服务器(用于快速搭建从库)
CLONE INSTANCE FROM 'admin'@'10.0.0.2':3306
  IDENTIFIED BY 'password';

六、定期维护任务

<code"># /usr/local/bin/mysql-maintenance.sh
#!/bin/bash
MYSQL="mysql -uroot -p'your_password'"

# 1. 更新表统计信息(优化查询计划)
$MYSQL -e "
SELECT CONCAT('ANALYZE TABLE ', table_schema, '.', table_name, ';')
FROM information_schema.tables
WHERE table_schema NOT IN ('mysql','information_schema','performance_schema','sys')
" | grep ANALYZE | $MYSQL

# 2. 检查表空间碎片率(高碎片率影响性能)
$MYSQL -e "
SELECT table_name,
       ROUND(data_free / 1024 / 1024, 2) AS free_mb,
       ROUND(data_free / (data_length + index_length) * 100, 2) AS frag_pct
FROM information_schema.tables
WHERE table_schema = 'mydb'
  AND data_free > 100 * 1024 * 1024  -- 超过100MB碎片
ORDER BY data_free DESC;"

# 3. 重建碎片化严重的表(在业务低峰期执行)
# ALTER TABLE orders ENGINE=InnoDB;  -- 重建表,释放碎片

echo "每周日凌晨4点执行"

七、总结

MySQL 8.0 生产调优的优先级:innodb_buffer_pool_size(首要,设总内存60%)→ ProxySQL 连接池(控制并发)→ 慢查询日志开启(发现问题)→ 执行计划分析(定位索引缺失)→ 定期维护(保持统计信息准确)。按此顺序优化的香港服务器,MySQL 吞吐量通常可以提升 3~5 倍,P99 查询延迟降低 60% 以上,为上层应用提供稳定的数据库支撑。

Telegram