适配说明:本教程针对源码安装在 /usr/local/mysql 路径的 mysql 服务,全程无安装步骤,覆盖 openeuler 系统全场景故障排查、根因定位、解决方案及全维度性能优化,适配 x86 / 鲲鹏 arm 架构,兼容 mysql 5.7/8.0 主流版本。
一、前置环境信息确认(排查前必做)
所有故障排查的前提是确认基础环境一致性,避免因路径、权限、配置加载顺序错误导致无效排查。
1. 核心目录与路径确认(/usr/local 专属)
表格
| 配置项 | 标准路径 | 查看命令 |
|---|---|---|
| 基础安装目录 (basedir) | /usr/local/mysql | mysqld --verbose --help | grep -a 1 "basedir" |
| 数据目录 (datadir) | /usr/local/mysql/data | mysqld --verbose --help | grep -a 1 "datadir" |
| 配置文件加载顺序 | /etc/my.cnf > /etc/mysql/my.cnf > /usr/local/mysql/my.cnf > ~/.my.cnf | mysqld --verbose --help | grep -a 2 "default options" |
| 错误日志路径 | 默认 /usr/local/mysql/data/ 主机名.err | mysql -uroot -p -e "show variables like 'log_error';" |
| socket 文件路径 | 默认 /tmp/mysql.sock | mysql -uroot -p -e "show variables like 'socket';" |
| pid 文件路径 | /usr/local/mysql/data/mysqld.pid | mysqld --verbose --help | grep -a 1 "pid-file" |
2. 基础环境校验
- 环境变量配置:确保 mysql 命令可全局调用
# 临时生效 export path=$path:/usr/local/mysql/bin # 永久生效(openeuler系统) echo "export path=\$path:/usr/local/mysql/bin" >> /etc/profile source /etc/profile # 验证 mysql --version
- 运行用户校验:确认 mysql 用户 / 用户组存在,且目录权限正确
# 检查mysql用户 id mysql # 修复目录所属权(高频故障点) chown -r mysql:mysql /usr/local/mysql/data chmod -r 700 /usr/local/mysql/data chown -r mysql:mysql /usr/local/mysql/logs # 如有独立日志目录
- systemd 服务文件校验:源码安装高频故障点,确保服务文件路径正确
# 查看服务文件路径 systemctl cat mysqld.service # 核心配置校验(必须匹配/usr/local路径) [service] user=mysql group=mysql execstart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf limitnofile=65535
二、mysql 故障排查通用标准化流程
90% 的 mysql 故障可通过该流程快速定位根因,禁止跳步排查,优先定位故障大类,再深入细节。
第一步:故障现象初步分类
先明确故障类型,缩小排查范围:
- 启动失败类:systemctl start mysqld 执行失败,服务无法进入 running 状态
- 连接异常类:服务正常运行,但本地 / 远程无法登录,报各类连接错误
- 性能异常类:服务可正常连接,但 sql 执行慢、业务卡顿、cpu/io 负载飙升
- 数据异常类:表损坏、数据丢失、主从同步中断、死锁 / 锁等待报错
- 服务崩溃类:服务运行中意外退出、被 oom 杀死、频繁重启
第二步:优先查看错误日志(核心中的核心)
mysql 绝大多数故障都会在错误日志中留下明确根因,这是排查的第一优先级。
- 日志查看命令
# 方式1:根据配置文件路径查看(推荐)
tail -n 100 -f $(mysql -uroot -p -e "show variables like 'log_error';" | grep -v "variable_name" | awk '{print $2}')
# 方式2:默认路径查看(启动失败无法登录时用)
tail -n 100 -f /usr/local/mysql/data/$(hostname).err
# 方式3:查看systemd系统日志(启动失败无mysql日志时用)
journalctl -u mysqld.service -f --no-pager- 日志核心排查要点
- 重点搜索关键字:
[error]、[warning]、permission denied、address already in use、no space left on device、innodb: error、oom - 启动失败优先看:配置文件语法错误、路径不存在、权限不足、端口占用、内存不足、innodb 文件损坏
- 运行中崩溃优先看:oom killer 日志、内存参数溢出、io 异常、内核报错
第三步:系统资源与服务状态排查
- 服务状态基础检查
# 查看服务运行状态 systemctl status mysqld.service # 查看mysqld进程是否存在 ps -ef | grep mysqld | grep -v grep # 检查端口是否正常监听(默认3306) ss -tulpn | grep mysqld netstat -tulpn | grep 3306
- 系统资源瓶颈排查
# 1. 磁盘空间检查(高频故障点:datadir分区满、inode耗尽) df -h /usr/local/mysql/data df -i /usr/local/mysql/data # 2. 内存检查(oom、内存不足) free -mh # 查看是否有oom杀死进程记录 dmesg | grep -i "oom" | grep -i "kill" journalctl -k | grep -i oom # 3. cpu/io负载检查 top # 按p看cpu排序,按m看内存排序 iostat -x 5 3 # 查看%iowait、%util磁盘io负载 vmstat 5 3 # 查看系统上下文切换、阻塞进程
- 系统安全组件排查(openeuler 特有高频故障点)
# 1. 防火墙检查(远程连接失败核心原因) # 查看防火墙状态 firewall-cmd --state # 查看已放行端口 firewall-cmd --list-ports # 临时放通3306端口 firewall-cmd --add-port=3306/tcp # 永久放通 firewall-cmd --add-port=3306/tcp --permanent firewall-cmd --reload # 2. selinux检查(启动失败、权限报错核心原因) # 查看selinux状态 getenforce # 临时关闭(验证是否为selinux导致) setenforce 0 # 永久关闭(需重启服务器) sed -i 's/^selinux=.*/selinux=disabled/' /etc/selinux/config # 若不想关闭,添加selinux规则适配/usr/local路径 semanage fcontext -a -t mysqld_db_t "/usr/local/mysql/data(/.*)?" restorecon -rv /usr/local/mysql/data
第四步:配置文件合法性校验
配置文件错误是启动失败、性能异常的 top1 原因,尤其是源码安装的路径配置错误。
- 配置文件语法校验
# 全量校验配置文件合法性,有错误会直接输出(mysql 5.7+支持) mysqld --validate-config --defaults-file=/etc/my.cnf # 兼容低版本的校验方式 mysqld --verbose --help --defaults-file=/etc/my.cnf > /dev/null
- 核心配置项校验重点检查以下参数,确保路径、数值无错误:
basedir、datadir:必须与实际安装路径一致,目录必须存在且 mysql 用户有权限port、socket:客户端与服务端配置必须一致,端口无占用,socket 文件目录有权限pid-file:目录必须存在,mysql 用户有写入权限log_error:路径必须存在,mysql 用户有写入权限- 内存相关参数:总和不超过系统物理内存的 80%,避免 oom
第五步:数据库内部状态排查(可正常登录时执行)
若服务可正常登录,通过以下命令定位内部运行异常:
sql
-- 1. 查看当前所有连接,定位长事务、锁等待、异常sql show full processlist; -- 2. 查看innodb引擎状态,核心用于死锁、事务、io异常排查 show engine innodb status; -- 3. 查看数据库全局配置,确认参数是否生效 show variables like '%参数名%'; -- 4. 查看数据库运行状态指标,定位性能瓶颈 show global status like '%状态名%'; -- 5. 查看锁等待信息(mysql 8.0) select * from performance_schema.data_locks; select * from performance_schema.data_lock_waits; -- 6. 查看事务信息 select * from information_schema.innodb_trx;
三、高频故障场景专项排查与解决方案
场景 1:mysql 服务启动失败(最常见)
子场景 1.1 配置文件错误导致启动失败
- 现象:systemctl start mysqld 执行失败,journalctl 日志报
unknown variable、syntax error、unknown option - 排查步骤:
- 执行
mysqld --validate-config命令,查看具体的错误参数和行号 - 检查配置文件加载顺序,确认是否有多个配置文件冲突
- 检查参数拼写错误、格式错误(如缺少
=、多余空格、不支持的参数)
- 执行
- 解决方案:
- 注释或修正报错的参数,确保参数与 mysql 版本兼容
- 统一配置文件到
/etc/my.cnf,删除其他路径下的冗余配置文件 - 修正后重新执行校验命令,无报错后再启动服务
子场景 1.2 文件权限 / 所属权错误
- 现象:启动失败,错误日志报
can't create/write to file、permission denied、errcode: 13 - permission denied - 排查步骤:
- 查看错误日志,确认报错的文件 / 目录路径
- 检查 datadir、日志目录、pid 文件目录、socket 文件目录的所属用户和权限
- 解决方案:
bash
# 修复核心目录所属权 chown -r mysql:mysql /usr/local/mysql/data chown -r mysql:mysql /usr/local/mysql/logs # 如有独立日志目录 # 修复目录权限 chmod -r 700 /usr/local/mysql/data chmod -r 660 /usr/local/mysql/data/* # 修复socket文件权限(若存在) chown mysql:mysql /tmp/mysql.sock chmod 777 /tmp/mysql.sock
子场景 1.3 端口被占用
- 现象:启动失败,错误日志报
can't start server: bind on tcp/ip port: address already in use - 排查步骤:
ss -tulpn | grep 3306,查看占用 3306 端口的进程 - 解决方案:
- 若为冗余 mysqld 进程占用,执行
kill -9 进程id杀死进程后重新启动 - 若为其他程序占用,修改
/etc/my.cnf中的port参数,更换未被占用的端口 - 重启服务后验证端口监听状态
- 若为冗余 mysqld 进程占用,执行
子场景 1.4 磁盘空间 / inode 耗尽
- 现象:启动失败,错误日志报
no space left on device、write to file failed、innodb: error: write to file ibdata1 failed - 排查步骤:
df -h检查 datadir 所在分区磁盘使用率,确认是否 100% 占用df -i检查分区 inode 使用率,确认是否耗尽
- 解决方案:
- 清理无用文件:删除过期的 binlog 日志、大尺寸错误日志、临时文件
sql
-- 手动清理指定时间前的binlog(mysql内执行) purge binary logs before '2026-03-01 00:00:00';
- 调整 binlog 自动过期策略,避免无限增长(见优化章节)
- 若 inode 耗尽,删除大量小文件(如过期的慢日志分片、临时文件)
- 扩容 datadir 所在磁盘分区,完成后重新启动服务
子场景 1.5 内存不足 / oom 导致启动失败
- 现象:启动失败,错误日志报
cannot allocate memory,或服务启动后立即被杀死,dmesg 有 oom killer 日志 - 排查步骤:
free -mh查看系统可用内存,确认是否不足- 查看 my.cnf 中内存相关参数,计算总内存占用是否超过系统可用内存
- 解决方案:
- 调小核心内存参数,优先降低
innodb_buffer_pool_size(最占内存) - 临时增加 swap 分区,缓解内存压力
- 扩容服务器物理内存,重新调整内存参数后启动服务
- 调小核心内存参数,优先降低
子场景 1.6 innodb 数据文件损坏
- 现象:启动失败,错误日志报
innodb: error: tablespace id mismatch、innodb: database page corruption on disk、ibdata1 file corrupted - 排查步骤:查看错误日志,确认 innodb 文件损坏的具体表和类型
- 解决方案:
- 轻度损坏:通过强制恢复模式启动,备份数据后重建
bash
# 1. 停止服务 systemctl stop mysqld # 2. 编辑/etc/my.cnf,添加强制恢复参数(1-6,从1开始尝试,最小能启动的值) innodb_force_recovery = 1 # 3. 启动服务,成功后全量备份所有数据库 mysqldump -uroot -p --all-databases > all_database_backup.sql # 4. 停止服务,注释innodb_force_recovery参数,重建数据目录 # 5. 重新初始化后导入备份数据
- 重度损坏:直接从最近的全量备份恢复数据,配合 binlog 实现时间点恢复
子场景 1.7 systemd 服务文件配置错误
- 现象:systemctl 启动失败,但手动执行
mysqld_safe --user=mysql可正常启动 - 排查步骤:查看 mysqld.service 文件,检查
execstart、user、group、limitnofile配置 - 解决方案:
- 修正服务文件,确保路径与 /usr/local/mysql 完全匹配,标准配置如下:
ini
[unit] description=mysql server after=network.target [service] user=mysql group=mysql type=notify execstart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf execreload=/bin/kill -s hup $mainpid execstop=/bin/kill -s term $mainpid limitnofile=1048576 limitnproc=1048576 timeoutsec=600 restart=on-failure [install] wantedby=multi-user.target
- 重新加载 systemd 配置并启动
bash
systemctl daemon-reload systemctl start mysqld
场景 2:mysql 连接异常(服务正常,无法登录)
子场景 2.1 本地 socket 连接失败
- 现象:本地执行
mysql -uroot -p报错can't connect to local mysql server through socket '/tmp/mysql.sock' (2) - 排查步骤:
- 确认服务正常运行,端口正常监听
- 查看 my.cnf 中
[mysqld]和[client]段的 socket 配置是否一致 - 检查 socket 文件是否存在,权限是否正确
- 解决方案:
- 临时解决:指定正确的 socket 路径连接
bash
mysql -uroot -p -s /usr/local/mysql/data/mysql.sock
- 永久解决:统一
/etc/my.cnf中[mysqld]和[client]的 socket 配置
ini
[mysqld] socket = /tmp/mysql.sock [client] socket = /tmp/mysql.sock
- 重启服务,重新生成 socket 文件
子场景 2.2 远程连接失败
- 现象:本地可正常登录,远程客户端连接报错
host 'xxx.xxx.xxx.xxx' is not allowed to connect to this mysql server、connection timed out - 排查步骤:
- 网络连通性测试:远程端执行
telnet 服务器ip 3306,确认端口可访问 - 检查 openeuler 防火墙是否放通 3306 端口
- 检查 mysql 用户是否允许远程访问,host 字段是否为
%或指定 ip - 检查 my.cnf 中
bind-address是否绑定了 127.0.0.1
- 网络连通性测试:远程端执行
- 解决方案:
- 防火墙放通 3306 端口(见前文系统资源排查)
- 修正 bind-address 配置,允许远程访问
ini
# /etc/my.cnf 添加/修改,重启服务生效 bind-address = 0.0.0.0
- 创建允许远程访问的数据库用户
sql
-- 创建远程root用户(生产环境建议创建专用业务用户,限制权限) create user 'root'@'%' identified by '你的强密码'; grant all privileges on *.* to 'root'@'%' with grant option; flush privileges; -- 查看用户权限 select user,host from mysql.user where user='root';
子场景 2.3 连接数爆满报错 too many connections
- 现象:新连接报错
too many connections,业务无法连接数据库 - 排查步骤:
- 用 root 本地登录(mysql 为 root 预留了 1 个额外连接),执行
show variables like 'max_connections';查看最大连接数 - 执行
show global status like 'threads_connected';查看当前连接数 - 执行
show full processlist;查看是否有大量空闲睡眠连接、长事务
- 用 root 本地登录(mysql 为 root 预留了 1 个额外连接),执行
- 解决方案:
- 紧急恢复:kill 掉无用的空闲连接,释放连接数
- 临时调大最大连接数(重启后失效)
sql
set global max_connections = 2000;
- 永久生效:修改 /etc/my.cnf 配置
ini
max_connections = 2000
- 根因优化:调整连接超时参数,自动关闭空闲连接
ini
# 非交互式连接超时时间,单位秒,默认8小时,改为10分钟 wait_timeout = 600 # 交互式连接超时时间 interactive_timeout = 600
- 优化应用端连接池,设置合理的最大连接数和空闲连接回收机制
子场景 2.4 密码正确但登录报错 access denied
- 现象:密码确认正确,登录报错
access denied for user 'root'@'localhost' (using password: yes) - 排查步骤:
- 确认用户 host 是否匹配,比如 root@'localhost' 和 root@'%' 是两个不同用户
- 检查是否存在匿名用户,导致登录匹配优先级异常
- 确认用户认证插件是否与客户端兼容(mysql8.0 默认 caching_sha2_password,低版本客户端不兼容)
- 解决方案:
- 跳过权限表启动,重置密码
bash
# 1. 停止服务 systemctl stop mysqld # 2. 跳过权限表启动 /usr/local/mysql/bin/mysqld_safe --skip-grant-tables --skip-networking --user=mysql & # 3. 无密码登录 mysql -uroot # 4. 重置密码(mysql8.0) use mysql; flush privileges; alter user 'root'@'localhost' identified by '你的新密码'; flush privileges; exit; # 5. 停止跳过权限表的进程,正常启动服务
- 删除匿名用户,避免匹配异常
sql
delete from mysql.user where user=''; flush privileges;
- 兼容低版本客户端,修改认证插件
sql
alter user 'root'@'%' identified with mysql_native_password by '你的密码'; flush privileges;
场景 3:mysql 运行卡顿 / 性能异常
子场景 3.1 cpu 使用率飙升
- 现象:top 查看 mysqld 进程 cpu 占用 100%+,业务响应卡顿,qps 骤降
- 排查步骤:
show full processlist;定位正在执行的耗时 sql,查看是否有大量全表扫描、排序、分组操作- 开启慢查询日志,定位 top 慢 sql
- 用 explain 分析慢 sql 执行计划,确认是否未走索引、索引失效
- 解决方案:
- 紧急处理:kill 掉异常耗时的 sql,临时恢复业务
- 根因优化:为慢 sql 添加合适的索引,优化 sql 语句(避免 select *、避免函数操作索引字段、避免深分页)
- 避免大事务、长事务,拆分复杂 sql,减少 cpu 计算开销
- 限制并发数,优化应用端连接池,避免大量并发 sql 同时执行
子场景 3.2 磁盘 io 负载过高
- 现象:iostat 查看 % iowait、% util 持续飙升,磁盘读写频繁,sql 查询卡顿
- 排查步骤:
- 慢查询日志定位大量磁盘 io 的 sql(全表扫描、无索引的大表查询)
show engine innodb status;查看 innodb io 刷新情况- 检查 innodb_flush_log_at_trx_commit、sync_binlog 参数配置
- 解决方案:
- 优化 sql 和索引,减少全表扫描,降低磁盘 io 次数
- 调大 innodb_buffer_pool_size,增加数据缓存,减少磁盘读写
- 合理调整事务刷盘参数,平衡性能与安全
ini
# 金融核心场景:双1配置,最高安全性 innodb_flush_log_at_trx_commit = 1 sync_binlog = 1 # 非核心业务场景:高性能配置,宕机丢失1秒数据 innodb_flush_log_at_trx_commit = 2 sync_binlog = 1000
- 硬件优化:更换 nvme ssd,分离数据文件、binlog、日志到不同磁盘,避免 io 竞争
- 关闭 innodb_flush_neighbors(ssd 场景),减少不必要的邻页刷新
子场景 3.3 死锁与锁等待超时
- 现象:业务报错
lock wait timeout exceeded; try restarting transaction、deadlock found when trying to get lock - 排查步骤:
show engine innodb status;查看最近的死锁详细信息,定位死锁的 sql 和事务information_schema.innodb_trx查看当前运行的长事务performance_schema.data_locks查看当前持有和等待的锁
- 解决方案:
- 紧急处理:kill 掉导致锁等待的长事务,释放锁资源
- 优化 sql 和索引,避免全表扫描导致的表锁,减少锁范围
- 拆分大事务、长事务,缩小事务执行时间,减少锁持有时间
- 统一业务中事务的更新顺序,避免交叉更新导致死锁
- 调整行锁等待超时参数
ini
innodb_lock_wait_timeout = 10
场景 4:主从同步异常
- 现象:从库同步中断,
show slave status\g查看slave_io_running或slave_sql_running为 no - 排查与解决方案:
- io 线程为 no:
- 常见原因:主库网络不通、防火墙拦截、主从账号密码错误、主库 binlog 未开启、server-id 冲突、主库 binlog 文件丢失
- 解决方案:检查网络连通性、防火墙放通端口、确认同步账号权限、统一 server-id 集群内唯一、重新配置主从同步
- sql 线程为 no:
- 常见原因:主从数据不一致、主键冲突、从库写入、ddl 执行失败、binlog 格式不兼容
- 解决方案:
- 临时跳过单个错误(非核心数据):
stop slave; set global sql_slave_skip_counter=1; start slave; - 数据不一致场景:通过 pt-table-checksum 校验数据差异,pt-table-sync 修复数据,或重新全量同步主库数据
- 临时跳过单个错误(非核心数据):
- 主从延迟过高:
- 常见原因:从库性能不足、大事务执行、无主键表、并行复制未开启、网络延迟
- 解决方案:开启 mysql8.0 并行复制、拆分大事务、确保所有表有主键、提升从库硬件配置、优化主库写入频率
- io 线程为 no:
四、mysql 全维度性能优化
优化核心原则:先优化业务 sql 与索引,再优化配置参数,最后优化系统与架构,80% 的性能问题都可通过 sql 与索引优化解决。
一、sql 与索引优化(优先级最高)
1. 慢查询日志开启与分析
慢查询是性能问题的核心来源,生产环境必须开启,用于定位耗时 sql。
# /etc/my.cnf 慢查询配置 slow_query_log = on # 日志路径,确保mysql用户有写入权限 slow_query_log_file = /usr/local/mysql/data/slow.log # 慢查询阈值,单位秒,超过1秒的sql记录,生产环境可设为0.5 long_query_time = 1 # 记录未使用索引的sql log_queries_not_using_indexes = on # 限制每分钟未使用索引的sql记录次数,避免日志暴涨 log_throttle_queries_not_using_indexes = 10
慢日志分析工具:
# 1. 自带mysqldumpslow,按执行时间排序,取top10慢sql mysqldumpslow -s t -t 10 /usr/local/mysql/data/slow.log # 2. 进阶工具pt-query-digest(percona-toolkit),生成详细分析报告 pt-query-digest /usr/local/mysql/data/slow.log > slow_report.log
2. 执行计划 explain 分析
通过 explain 分析 sql 执行计划,定位索引失效、全表扫描等问题,核心用法:
explain select * from 表名 where 条件;
核心字段关注重点:
表格
| 字段 | 优化要点 |
|---|---|
| type | 访问类型,最优到最差:system > const > eq_ref > ref > range > index > all,必须避免 all(全表扫描) |
| key | 实际使用的索引,为 null 表示未使用索引,需优化 |
| rows | 扫描的行数,数值越小越好,代表索引效率越高 |
| extra | 避免出现using filesort(文件排序)、using temporary(临时表)、using where无索引匹配 |
3. 索引优化最佳实践
- 高频查询字段优先建索引:where 条件、join 关联字段、order by、group by 字段
- 联合索引遵循最左前缀原则,区分度高的字段放在索引前列
- 单表索引数量控制在 5 个以内,避免大量索引导致写入性能下降
- 避免索引失效场景:索引字段使用函数运算、隐式类型转换、like '% xxx' 前缀模糊查询、or 连接非索引字段、!=/not in 操作
- 定期删除无用、重复、低选择性的索引,通过 pt-index-usage 分析索引使用率
- 所有表必须有主键,优先使用自增主键,避免 uuid 作为主键
4. sql 编写优化规范
- 禁止使用 select *,只查询业务需要的字段,减少数据传输和内存占用
- 避免大表 join 大表,控制 join 的表数量不超过 3 个,join 字段必须建索引
- 避免在 where 子句中对索引字段进行函数、算术运算,导致索引失效
- 优化深分页查询,如
limit 100000,20,改为主键过滤分页where id > 100000 limit 20 - 批量操作代替循环单条操作,如批量 insert、update,减少数据库交互次数
- 拆分大事务、长事务,控制事务执行时间,避免锁持有时间过长
- 禁止在业务高峰期执行大表 ddl、alter table 操作,使用 pt-online-schema-change 工具无锁改表
二、mysql 配置参数优化(/etc/my.cnf)
以下为适配 /usr/local/mysql 安装路径、openeuler 系统的优化配置,按服务器内存调整核心参数。
1. 基础路径与通用配置
[mysqld] # 核心路径配置(必须与你的安装路径一致) basedir = /usr/local/mysql datadir = /usr/local/mysql/data socket = /tmp/mysql.sock pid-file = /usr/local/mysql/data/mysqld.pid port = 3306 user = mysql # 字符集配置 character-set-server = utf8mb4 collation-server = utf8mb4_general_ci lower_case_table_names = 1 # 表名大小写不敏感,openeuler系统建议开启 default-time_zone = '+8:00' # 禁用dns反向解析,提升连接速度 skip-name-resolve
2. 核心内存优化配置
内存优化核心原则:专用数据库服务器,mysql 总内存占用不超过系统物理内存的 70%,避免 oom。
表格
| 参数 | 优化建议 |
|---|---|
| innodb_buffer_pool_size | 最核心参数,innodb 数据和索引缓存,专用服务器设为物理内存的 50%-70%。例:8g 内存设 4g,16g 设 10g,32g 设 20g |
| innodb_buffer_pool_instances | 缓冲池实例数,缓冲池大于 8g 时设为 4-8 个,每个实例至少 1g,减少锁竞争 |
| innodb_log_buffer_size | redo log 缓冲区,高并发写入场景设为 64m-128m,最大不超过 1g,避免频繁刷磁盘 |
| sort_buffer_size | 每个会话排序缓冲区,默认 256k,建议不超过 4m,排序多的场景设 1m-2m |
| join_buffer_size | 每个会话 join 缓冲区,默认 256k,建议不超过 4m,避免大表 join 内存溢出 |
| read_buffer_size | 顺序读缓冲区,默认 128k,顺序扫描多的场景设 256k-1m |
| read_rnd_buffer_size | 随机读缓冲区,默认 256k,排序多的场景设 512k-1m |
3. innodb 引擎核心优化
# io刷新方式,绕过操作系统缓存,直接写入磁盘,ssd场景必选,减少双缓存和swap占用 innodb_flush_method = o_direct # 事务刷盘策略,见前文io优化,根据业务场景选择 innodb_flush_log_at_trx_commit = 1 # binlog刷盘策略,与上面参数配合,双1配置最高安全性 sync_binlog = 1 # 每个表独立表空间,必须开启,方便表维护、空间回收,避免ibdata1无限膨胀 innodb_file_per_table = on # io线程数,多核cpu建议设为8-16,提升io并发能力 innodb_read_io_threads = 16 innodb_write_io_threads = 16 # 脏页最大比例,避免脏页集中刷盘导致io抖动 innodb_max_dirty_pages_pct = 60 # 行锁等待超时时间,单位秒,业务场景建议5-10秒 innodb_lock_wait_timeout = 10 # 事务隔离级别,互联网业务推荐read-committed,减少锁等待,提升并发 transaction_isolation = read-committed # 关闭邻页刷新,ssd场景必关,hdd场景开启 innodb_flush_neighbors = 0 # io容量设置,根据ssd性能调整,普通ssd设2000,nvme ssd设4000-8000 innodb_io_capacity = 2000 innodb_io_capacity_max = 4000
4. 连接与日志优化
# 最大连接数,根据业务场景设置,建议1000-2000,避免设置过大 max_connections = 2000 # 连接超时时间,自动关闭空闲连接,单位秒 wait_timeout = 600 interactive_timeout = 600 # 最大错误连接数,避免频繁错误连接导致ip封禁 max_connect_errors = 1000 # binlog配置(主从同步、数据恢复必开) server-id = 1 # 集群内必须唯一 log_bin = /usr/local/mysql/data/mysql-bin binlog_format = row # 行级模式,推荐,主从同步更安全 binlog_row_image = full # binlog自动过期时间,7天,避免磁盘占满(mysql8.0推荐用秒级配置) binlog_expire_logs_seconds = 604800 # mysql5.7用天级配置 # expire_logs_days = 7 # 错误日志配置,排查故障核心,必须开启 log_error = /usr/local/mysql/data/mysql-error.log log_error_verbosity = 3
三、openeuler 系统级内核优化
openeuler 针对服务器场景深度优化,通过内核参数调整可大幅提升 mysql 性能,适配 x86 / 鲲鹏 arm 架构。
1. 内核参数优化(/etc/sysctl.conf)
编辑/etc/sysctl.conf,添加以下配置,执行sysctl -p立即生效。
# 内存优化 # 尽量不使用swap,数据库专用服务器设为1,避免swap导致性能暴跌 vm.swappiness = 1 # 脏页达到20%时,后台开始异步刷盘 vm.dirty_ratio = 20 # 脏页达到10%时,后台启动刷盘 vm.dirty_background_ratio = 10 # 严格控制内存分配,避免oom vm.overcommit_memory = 2 # 允许分配的内存不超过物理内存的80%+swap vm.overcommit_ratio = 80 # io优化 # 最大异步io数量,适配innodb fs.aio-max-nr = 1048576 # 系统级最大文件句柄数 fs.file-max = 2097152 # 网络优化,高并发连接场景 # 监听队列最大长度,默认128,高并发必须调大 net.core.somaxconn = 65535 # syn队列最大长度 net.ipv4.tcp_max_syn_backlog = 65535 # time_wait超时时间,默认60,调小减少端口占用 net.ipv4.tcp_fin_timeout = 30 # 允许time_wait端口复用,高并发必须开启 net.ipv4.tcp_tw_reuse = 1 # 最大time_wait数量 net.ipv4.tcp_max_tw_buckets = 200000 # 网络设备接收队列最大长度 net.core.netdev_max_backlog = 30000 # 端口范围,扩大可用端口数 net.ipv4.ip_local_port_range = 1024 65535 # 读写缓冲区最大值 net.core.rmem_max = 134217728 net.core.wmem_max = 134217728 # 鲲鹏arm架构专属优化(x86可忽略) kernel.sched_steal_node_limit=4
2. 文件句柄限制优化
mysql 需要大量文件句柄,默认 1024 远远不足,编辑/etc/security/limits.conf,添加以下配置,重启服务器生效。
mysql soft nofile 65535 mysql hard nofile 1048576 mysql soft nproc 65535 mysql hard nproc 1048576 root soft nofile 1048576 root hard nofile 1048576
生效后执行ulimit -n,确认输出为 65535 及以上。
3. io 调度器优化
- nvme ssd / 固态硬盘:推荐使用
none/noop调度器,减少 io 调度开销 - 机械硬盘 hdd:推荐使用
mq-deadline调度器,优化寻道效率
# 查看当前调度器(sda为你的磁盘名,根据实际修改) cat /sys/block/sda/queue/scheduler # 临时修改 echo none > /sys/block/sda/queue/scheduler # 永久生效:编辑/etc/default/grub,在grub_cmdline_linux中添加elevator=none,更新grub后重启生效
4. cpu 性能优化
关闭 cpu 节能模式,设置为性能模式,避免 cpu 降频导致性能波动。
# 临时设置为性能模式 cpupower frequency-set -g performance # 永久生效:在bios中关闭cpu节能模式,或配置systemd服务开机执行
四、架构级长期优化
- 读写分离:主库负责写入,从库负责读取,分担读压力,适配读多写少的业务场景
- 分库分表:单表数据量超过 1000 万、单库容量超过 100g 时,实施水平 / 垂直分库分表,降低单表负载
- 缓存架构:搭配 redis 缓存热点数据、高频查询结果,减少 mysql 数据库访问压力
- 高可用架构:部署 mgr(mysql group replication)、keepalived + 双主架构,避免单点故障,提升服务可用性
- 冷热数据分离:历史冷数据归档到单独的库 / 表,热数据保留在主库,大幅提升查询性能
五、日常运维与故障预防
- 日常巡检核心项:
- 服务状态、端口监听、主从同步状态
- 磁盘空间使用率、binlog 增长情况
- cpu、内存、io 负载是否有异常飙升
- 错误日志是否有新增 error 告警
- 慢查询日志是否有新增异常慢 sql
- 当前连接数、锁等待、长事务情况
- 监控告警部署:
- 推荐使用
prometheus + grafana + mysqld_exporter搭建监控体系,覆盖连接数、qps/tps、缓存命中率、io 延迟、主从延迟等核心指标 - 设置磁盘空间、cpu 负载、服务状态、主从中断的告警规则,提前发现风险
- 推荐使用
- 备份策略:
- 制定定期备份计划:每日全量备份 + 每小时 binlog 增量备份
- 备份文件异地存储,定期执行备份恢复测试,确保备份可用
- 生产环境禁止在业务高峰期执行备份,大库推荐使用
percona-xtrabackup热备工具
- 常用运维工具推荐:
- percona-toolkit:mysql 运维神器,包含慢日志分析、表同步、无锁改表、索引分析等工具
- pt-stalk:故障捕获工具,异常时自动捕获系统和数据库状态,用于事后排查
- binlog2sql:binlog 解析工具,生成回滚 sql,用于误删数据恢复
- sysbench:mysql 压测工具,用于验证优化效果、性能测试
重要注意事项
- 所有配置修改、参数优化,必须先在测试环境验证,再上线生产环境,避免配置错误导致服务不可用
- 优化参数循序渐进,每次仅修改 1-2 个核心参数,观察性能变化,避免一次性修改大量参数导致无法定位问题
- 生产环境任何数据修改、表结构变更、服务重启,必须先备份,制定回滚方案,避免数据丢失
- 生产环境禁止开启通用查询日志 general_log,会严重影响数据库性能,仅临时排查问题时使用
- 注意 mysql 版本与 openeuler 系统的兼容性,鲲鹏 arm 架构必须使用对应 arm 版本的 mysql 安装包,避免兼容性问题
到此这篇关于openeuler系统mysql故障排查终极指南实战教程的文章就介绍到这了,更多相关openeuler mysql故障排查内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论