MySQL故障排查与生产环境优化
目录
一:MySQL单实例故障排查
(1)故障现象1
(2)故障现象2
(3)故障现象3
(4)故障现象4
(5)故障现象5
(6)故障现象6
(7)故障现象7
(8)故障现象8
二:MySQL主从故障排查
(1)故障现象1
(2)故障现象2
(3)故障现象3
三:MySQL优化
(1)硬件方面
1.关于cpu
2.关于内存
3.关于磁盘
(2)MySQL配置文件
1.核心性能优化项
2.查询优化项
3.日志与监控
4.InnoDB 高级优化
5.示例配置片段
(3)SQL方面
1.创建测试表并插入数据
2.使用EXPLAIN进行SQL优化的步骤及实验验证
3.优化步骤:添加索引
4.优化后查询及EXPLAIN分析
一:MySQL单实例故障排查
(1)故障现象1
ERROR 2002 (HY000) : Can't connect to local MySQL server through socket
' /data/mysql/mysql.sock' (2)
问题分析:以上这种情况一般都是数据库未启动、mysql配置文件未指定socket文件或者数据库端口被防火墙拦截导致。
解决方法:启动数据库或者防火墙开放数据库监听端口。
(2)故障现象2
ERROR 1045 (28000) : Access denied for user 'root'@'localhost' (using password: ON)
问题解析:密码不正确或者没有权限访问。
解决方法:
> 修改my.cnf 主配置文件,在[mysqld]下添加skip-grant-tables=on。重启数据库。最后修改密码
Mysq15.7版本
mysql> update mysql.user set authentication_string=password (' 123456')
where user='root'
and Host= 'localhost';
mysql> flush privileges;
Mysq18.0
mysql> UPDATE mysql.user SET authentication_string='WHERE user=' root'
AND Host='localhost';
mysql> FLUSH PRIVILEGES;
mysql>ALTER USER 'root'@'localhost'
IDENTIFIED BY '123456';
> 在删除刚刚添加的skip-grant-tables参数,重启数据库,使用新密码即可登录,重新授权。
Mysql5.7
mysql>grant all on *.* to 'root'@'mysql-server' identified by '123456
Mysq18.0
mysql> CREATE USER 'root'@'mysql-server' IDENTIFIED BY ' 123456'
mysql> GRANT all ON *.* TO 'root'@mysql-server';
(3)故障现象3
在使用远程连接数据库时偶尔会发生远程连接数据库很慢的问题
问题分析:如果MySQL主机查询DNS很慢或是由很多客户端主机时会导致连接很慢,由于开发机器时不能够连接外网的,在进行MySQL连接时,DNS解析时不可能完成的,从而也就明白了为什么连接那么慢了。
解决方法:修改my.cnf主配置文件,在[mysqld]下添加skip-name-resolve,重启数据库可以解决。注意在以后授权里面不能在使用主机名授权。
(4)故障现象4
Can't open file: 'xxx_forums. MYI'. (errno: 145)
问题解析:
> 服务器非正常关机,数据库所在空间已满,或一些其他未知的原因,对数据库表造成了损坏。
> 可能是操作系统下直接将数据库文件拷贝移动,会因为文件的属组问题而产生这个错误。
解决方法:
> 可以使用下面的两种方式修复时间表(第一种方法仅适合独立主机用户)
· 使用MySQL自带的专门用户设计表检查和修复工具 myisamchk。一般情况下只有在命令行下面才能运行myisamchk命令。常用的修复命令为:
myisamchk -r 数据文件目录/数据表名.MYI;
· 通过 phpMyAdmin修复,phpMyAdmin带有修复数据表的功能,进入到某一个表中后,点击"操作",在下方的"表维护"中点击"修复表"即可。
注意:以上两种修复方式在执行前一定要备份数据库。
> 修改文件的属组(仅适合独立主机用户):
· 复制数据库文件的过程中没有将数据库文件设置为MySQL运行的帐号可读写(一般适用于Linux和FreeBSD用户)。
(5)故障现象5
ERROR 1129 (HY000) : Host 'xxx.xxx.xxx.xxx' is blockeed because of many
connection errors;
unblock with 'mysqladmin flush-hosts'
问题分析: 由于mysql数据库的参数:max_connect_errors,其其默认值是10当大量(max_connect_errors)的主机去连接 MySQL,总连接请求超过了10次新的连接就再也无法连接上MySQL服务。同一个ip在短时间内产生太多中断的数据库连接而导致的阻塞(超过mysql数据库max_connection_errors的最大值)。
解决方法:
> 使用mysqladminflush-hosts命令清除缓存,命令执行方法去如下
mysqladmin -uroot -p -h 192.168.241.48 flush-hostS
Enter password:
> 修改mysql配置文件,在[mysqld]下面添加max_connect_erreors=1000,然后重启MySQL。
(6)故障现象6
客户端报Toomany connections。
问题分析: 连接数超出Mysql的最大连接数限制。
解决方法:
> 在my.cnf配置文件里面增大连接数,然后重启MySQL服务
max_connections = 10000
> 临时修改最大连接数,重启后不生效。需要在my.cnf里面修改配置文件,下次重启生效。
set GLOBAL max_connections=10000;
(7)故障现象7
Warning: World-writable config file '/etc/my.cnf' is ignored
ERROR! MySQL is running but PID file could not be found
问题分析:MySQL的配置文件/etc/my.cnf 权限不对。
解决方法:
chmod 644 /et/my.cnf
(8)故障现象8
InnoDB: Error: page 14178 log sequence number 29455369832
InnoDB: is in the future! Current system log sequence number 29455369832
问题分析:innodb数据文件损坏。
解决方法:修my.cnf配置文件,在[mysqld]下添加 innodb_force_recovery=4,启动数据库后备份数据文件,然后去掉该参数,利用备份文件恢复数据。
二:MySQL主从故障排查
(1)故障现象1
从库的Slave_I0_Running为NO
The slave I/0 thread stops because master and slave have equal MySQL serverids; these ids must be different for replication to work (or the--replicate-same-server-id option must be used on slave but this does not always make sense; please check the manual before using it).
问题分析:主库和从库的server-id值一样。
解决方法:修改从库的server-id的值,修改为和主库不一样。修改完后重启,再同步即可。
(2)故障现象2
从库的Slave_I0_Running为NO
问题分析:造成从库线程为NO的原因会有很多,主要原因是主键冲突或者主库删除或更新数据,从库找不到记录,数据被修改导致。通常状态码报错有1007、
1032、1062、1452等。
解决方法一:
mysql> stop slave;
mysql> set_GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
mysql> start slave;
解决方法二:
设置用户权限,设置从库只读权限
set global read_only=true;
(3)故障现象3
Error initializing relay log position: I/0 error reading the header from the binary log
分析问题:从库的中继日志relay-bin损坏。
解决方法:手工修复,重新找到同步的binlog和pos点,然后重新同步即可
mysql>CHAN GEMASTER TO MASTER_LOG_FILE=' mysql-bin. xx' , MASTER_LOG_POS=xxx;
三:MySQL优化
(1)硬件方面
1.关于cpu
CPU对于MySQL应用,推荐使用S.M.P.架构的多路对称CPU。例如:可以使用两颗IntelXeon3.6GHz的CPU。现在比较推荐用4U的服务器来专门做数据库服务器,不仅仅是针对于MySQL。
2.关于内存
物理内存对于一台使用MySQL的DatabaseServer来说,服务器内存建议不要小于2GB,推荐使用4GB以上的物理内存。不过内存对于现在的服务器而言可以说是一个可以忽略的问题,工作中遇到了高端服务器基本上内存都超过了32G。
3.关于磁盘
磁盘寻道能力(磁盘I/0)。以目前市场上普遍高转速SAS硬盘(15000转/秒)为例,这种硬盘理论上每秒寻道15000次,这是物理特性决定的,没有办法改变。MySQL每秒钟都在进行大量、复杂的查询操作,对磁盘的读写量可想而知。所以通常认为磁盘I/0是制约MySQL性能的最大团因素之一,通常是使用RAID-0+1磁盘阵列,注意不要尝试使用RAID-5,MySQL在ERAID-5磁盘阵列上的效率并不高。如果不考虑硬件的投入成本,也可以考虑固态(SSD)硬盘专门作为数据库服务器使用。数据库的读写性能肯定会提高很多。
(2)MySQL配置文件
1.核心性能优化项
参数 | 作用 | 建议配置 | 注意事项 |
innodb_buffer_pool_size | 存储索引和数据的内存区域,对 InnoDB 表性能影响极大 | 物理内存的 50%-75%(大内存服务器建议更高比例) | 需缓慢调整,防止 swap 出现 |
innodb_log_file_size | 单个 redo 日志文件大小,影响事务写入性能 | 1GB-2GB(根据写入负载调整,大事务场景建议更大值) | 调整需重建日志文件(需重启); |
innodb_flush_log_at_trx_commit | 控制事务提交时日志写入策略(影响 ACID 中的 D) | 1(默认,强持久化但有 IO 开销) | 对写入密集型系统,设为 2 可显著提升性能,但需权衡数据安全性 |
max_connections | 最大允许的客户端连接数 | 根据应用需求调整,建议不超过 1000(需结合 wait_timeout 参数) | 过高会导致内存耗尽;需监控 Threads_connected 状态变量 |
tmp_table_size | 内存临时表的最大大小 | 64M-256M(根据查询复杂度调整) | 过大可能导致内存溢出;临时表超过此值会转为磁盘表(性能显著下降 |
max_heap_table_size | 内存表的最大大小 | 与 tmp_table_size 保持一致 | 需防止应用创建过大的 MEMORY 表 |
2.查询优化项
参数 | 作用 | 建议配置 |
query_cache_type | 查询缓存类型(MySQL8.0已移除,旧版本慎用) | OFF(默认,高并发下建议关闭)。 |
sort_buffer_size | 排序操作缓冲区大小。 | 2M~8M,过大浪费内存 (如4M)。 |
join_buffer_size | JOIN操作缓冲区大小。 | 4M~16M,仅对无索引 JOIN有效(如8M)。 |
read_buffer_size | 顺序读缓冲区大小。 | 2M 8M(如4M) |
read_rnd_buffer_size | 随机读缓冲区大小。 | 4M16M(如 8M)。 |
3.日志与监控
参数 | 作用 | 建议配置 |
slow_query_log | 启用慢查询日志,记录执行时间长的SQL。 | ON |
long_query_time | 定义慢查询阈值(秒)。 | 1~2(根据业务容忍度调整) |
log_error | 错误日志路径,用指于故障排查。 | 用指定路径 (如/var/10g/mysql/error.log) |
binlog_format | 二进制日志格式(主从复制依赖)。 | ROW(推荐,数据一致性高) |
expire_logs_days | 自动清理旧的二进制日志天数。 | 7~14(根据备份策略调整) |
4.InnoDB 高级优化
参数 | 作用 | 建议配置 |
innodb_io_capacity | InnoDB 后台任务的 I/0能力(如刷新脏页)。 | SSD建以2000~4000 HDD建议200·400。 |
innodb_flush_method | 控制数据文件与日志 文件的刷新方式。 | 0_DIRECT(默认,避免双缓冲)。 |
innodb_thread_concurrency | InnoDB并发线程数 限制。 | 0(默认,自适应),高并发场景可设为 CPU核数*2。 |
innodb_autoinc_lock_mode | 自增锁模式,影响插入性能。 | 2(连续模式,高并发插入推 荐)。 |
5.示例配置片段
物理资源32核CPU、64G内存、500GSSD
[mysqld]
#核心配置
innodb_buffer_pool_size = 40G
innodb_log_file_size = 2G
innodb_flush_log_at_trx_commit = 2
max_connections = 1000
thread_cache_size = 100
#查询优化
tmp_table_size = 128M
max_heap_table_size = 128Msort_buffer_size = 4M
join_buffer_size = 8M
#日志与监控
slow_query_log = ON
long_query_time = 1
log_error=/var/log/mysql/error.log
binlog_format = ROW
expire_logs_days = 7
#InnoDB高级
innodb_io_capacity = 2000
innodb_flush_method = O_DIRECT
innodb_thread_concurrency = 0
innodb_autoinc_lock_mode = 2
(3)SQL方面
SQL优化是确保数据库高效运行的关键,其核心在于通过减少资源消耗(如CPU、内存、磁盘I/0)来提升查询响应速度,避免慢查询导致用户体验下降或系统崩溃。未优化的SQL可能引发全表扫描、冗余计算或钱竞争,尤其在数据量大或高并发场景下,会导致服务器负载飙升、响应延迟,甚至至影响业务连续性(如交易超时)。通过索引调优、查询改写、执行计划分析等手段,可显著降低数据库压力,支撑业务规模扩展,同时控制硬件成本与运维复杂度
1.创建测试表并插入数据
#创建测试库
Create database test;#创建用户表
Use test;CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
age INT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
#插入 10 万条测试数据(使用存储过程生成)
DELIMITER $$
CREATE PROCEDURE insert_users()
BEGIN
DECLARE i INT DEFAULT 0;
WHILE i < 100000 DO
INSERT INTO users (name, email, age)
VALUES (CONCAT('user', i), CONCAT('user', i, '@example.com'), FLOOR(RAND() * 100));
SET i = i + 1;
END WHILE;
END$$
DELIMITER ;CALL insert_users();
2.使用EXPLAIN进行SQL优化的步骤及实验验证
EXPLAIN 是MySQL中用于分析SQL执行计划的工具,通过模拟查询执行过程输出关键信息(如访问类型 type、使用索引 key、预估扫描行数 rows、额外操作 Extra等),帮助开发者识别全表扫描、索引失效等性能瓶颈,从而指导优化方向(如添加索引、改写查询或调整表结构),是提升数据库效率不可或缺的诊断手段。
3.优化步骤:添加索引
mysql>ALTER TABLE users ADD INDEX idx_name (name);
4.优化后查询及EXPLAIN分析
mysql>EXPLAIN SELECT * FROM users WHERE name ='user123';