mysql故障排查与环境优化

一、mysql运行原理

mysql的运行分为三层

客户端和连接服务

核心服务功能(sql接口、缓存的查询、sql的分析和优化以及部分内置函数的执行等。)

存储引擎层(负责mysql中数据的存储和提取。)

sql 复制代码
二、示例
1、实验环境
	单台mysql
	1主+1从
2、mysql单实例故障排查
现象1:
	ERROR 2002 (HY000):can't connect to local MySQL server through socket '/data/mysql/mysql.sock'(2)

分析:
	一般是数据库未启动、mysql配置文件未指定socket文件或者数据库端口被防火墙拦截导致。

解法:
	启动数据库或者防火墙开放数据库监听端口。

现象2:
	ERROR 1045 (28000):Access denied for user 'root'@'localhost' (using password:NO)

分析:
	密码不正确或没有权限访问。

解法:
	修改my.cnf主配置文件,在[mysqld]下添加skip-grant-talbes=on,重启数据库,最后修改密码命令如下。	

5.7版本
mysql> update mysql.user set authentication_string=password('123456') where user='root' and Host='localhost';
mysql> flush privileges;

8.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参数,重启数据库,使用新密码即可登录。重新授权,命令如下。

5.7版本
mysql> grant all on *.* to 'root'@'mysql-server' identified by '123456';

8.0版本
mysql> create user 'root'@'mysql-server' identified  by '123456';
mysql> grant all on *.* to 'root'@'mysql-server';

现象3:
	在使用远程连接数据库时偶尔会发生远程连接数据库很慢的问题。

分析:
	开启了dns解析功能。

解法:
	修改my.cnf主配置文件,在[mysqld]下添加skip-name-resolve,重启数据库可以解决。注意在以后授权里面不能再使用主机名授权。

现象4:
	Can't open file: 'xxx_forums.MYI'. (error:145)

分析:
	服务器非正常关机,数据库所在空间已满,或一些其它未知的原因,对数据库表造成了孙环。
	可能是操作系统下直接将数据库文件拷贝移动,会因为文件的属组问题而产生这个错误。

解法:
	myisamchk -r 数据文件目录/数据表名.MYI;  # 仅适合独立主机用户。
	
	或
	
	修改文件的属组。复制数据库文件的过程中没有将数据库文件设置为MySQL运行的账号可读写。 # 仅适合独立主机用户。

现象5:
	ERROR 1129 (HY000):Host 'xxx.xxx.xxx.xxx' is blocked because of many connection errors;
	unblock with 'mysqladmin flush-hosts'

分析:
	超出了mysql的总连接请求数,新的连接会无法连接。

解法:
	使用mysqladmin flush-hosts命令清除缓存即可。
	mysqladmin -uroot -p -h ip flush-hosts 

	或
	
	修改mysql配置文件,在[mysqld]下面添加max_connect_errors=1000,然后重启。

现象6:
	客户端报 Too many connections.

分析:
	连接数超出mysql的最大连接数限制。

解法:
	在my.cnf配置文件中增大连接数,然后重启mysql
	max_connections=1000
	
	或

	临时修改最大连接数。
	set GLOBAL max_connections=1000;

现象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 /etc/my.cnf

现象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
	从库的Slave_IO_Running 为 NO
	The slave I/O thread stops because master and slave have equal MySQL server ids; 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值,与主库不一样,重启mysql后再同步即可。

现象2
	从库的Slave_IO_Running 为 NO
	
分析:
	原因很多,例如主键冲突、主库删除,从库找不到记录、数据被修改导致。通常状态码报错有1007、1032、1062、1452等。

解法:
mysql> stop slave; 
mysql> set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;  # 设置全局sql从属计数器为1.
mysql> start slave;

或

mysql> set global read_only=true; # 设置用户权限,从库只读。

现象3
	Error initializing relay log position: I/O error reading the header from the binary log

分析:
	从库的中继日志relay-log损坏。

解法:
	手工修复,重新找到同步的binlog和pos点,然后重新同步即可。
	mysql>chan gemaster to master_log_file='mysql-bin.xxxxxx',master_log_pos=xxx;


mysql的sql语句优化

创建测试表并插入数据
mysql> create database test;
Query OK, 1 row affected (0.02 sec)

mysql> use test;
Database changed
mysql> 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
    -> );
Query OK, 0 rows affected (0.04 sec)

mysql> delimiter $$  # 设置分隔符,用$$来作为当前语句的终止符,以便后续存储过程使用它作为分隔符。
mysql> create procedure ii_users()  # 创建存储程序
    -> begin  # 开始存储程序。
    -> declare i int default 0;  # 声明变量。
    -> while i < 100000 do  # 执行循环插入数据。当i小于10万时,进入循环,name列由concat('user',i)生成,如user1、user2等,email列由concat('user',i,'@example.com')生成,如'user1@example.com',age列通过floor(rand() * 100) 随机生成0到99之间的整数值。 通过 i = i + 1 来更新变量的值。
    -> 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$$  #结束存储程序,使用之前的$$作为终止符。
Query OK, 0 rows affected (0.01 sec)
mysql> delimiter ;  # 恢复语句分隔符,将默认的语句分隔符恢复为; 避免后续查询出错。
mysql> call ii_users();   # 执行存储过程。
Query OK, 1 row affected (6 min 34.95 sec)

mysql> explain select * from users where name = 'user123';
+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+
|  1 | SIMPLE      | users | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 99909 |    10.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

mysql> alter table users add index idx_name(name);  # 优化,创建索引。
Query OK, 0 rows affected (0.68 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> explain select * from users where name = 'user123';  # 查询使用了索引,大大提高了查询效率。
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key      | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | users | NULL       | ref  | idx_name      | idx_name | 152     | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------+

explian用于显示mysql如何执行一条sql语句,关键字段解释:
字段 说明 优化关注点
id 查询序列号,相同id为同一执行层,不同id按序执行。

select_type 查询类型(simple、primary、subquery、derived等) 识别子查询或临时表操作。

table  访问的表名或别名。  确认查询涉及的表。

type  访问类型 性能从优到劣:system > const > eq_ref > ref > range > index > ALL 避免ALL(全表扫描),优先优化为ref或range。

possible_keys 可能使用的索引    检查是否有合适索引未被使用。

key  实际使用的索引    确认是否命中最佳索引

rows 预估扫描的行数	行数越少,查询效率越高。

extra	附加信息(如 using where 、using index、using temporary等) 发现潜在性能问题(如临时表、文件排序)。
相关推荐
随风飘的云15 分钟前
mysql的innodb引擎对可重复读做了那些优化,可以避免幻读
mysql
NineData11 小时前
NineData 迁移评估功能正式上线
数据库·dba
NineData16 小时前
数据库迁移总踩坑?用 NineData 迁移评估,提前识别所有兼容性风险
数据库·程序员·云计算
赵渝强老师19 小时前
【赵渝强老师】PostgreSQL中表的碎片
数据库·postgresql
全栈老石1 天前
拆解低代码引擎核心:元数据驱动的"万能表"架构
数据库·低代码
倔强的石头_2 天前
kingbase备份与恢复实战(二)—— sys_dump库级逻辑备份与恢复(Windows详细步骤)
数据库
jiayou643 天前
KingbaseES 实战:深度解析数据库对象访问权限管理
数据库
于眠牧北3 天前
MySQL的锁类型,表锁,行锁,MVCC中所使用的临键锁
mysql
李广坤4 天前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
Turnip12025 天前
深度解析:为什么简单的数据库"写操作"会在 MySQL 中卡住?
后端·mysql