《MySQL排查指南》简记

排查指南

1 记录查询

set global general_log='on';
set global log_output='table'; 
select argument.event_time from mysql.general_log where thread_id = this_thread_id order by event_time;# 改查询将返回锁定线程执行的查询列表 

或是file --->select * from mysql.grneral_log\G
` 常用存入文件的方式,方便监控查看整体执行的动作

2 select 优化,索引会降低数据更新的效率(特别是insert),要从整个业务的性能出发

1.将查询拆成小段
2.explain +  show warnings;

`非唯一的行不会产生eq_ref或更好的类型
`列中重复值很多时,不适合建立索引`

不要只看explain,要看实际执行的时间。

以下仅测试使用,因为要相信优化器,可能和高版本的优化冲突,反而用不上新特性
ignore index #忽略索引
force index #强制使用某索引

#在优化任何单个查询的时候,请时刻注意整个业务的性能

3 perror + mysql error code

perror 150

#http://bugs.mysql.com

4 主从数据不一致(复制不检查数据一致性)

`推荐基于row或者重写存储过程,使其不依赖已经存在的临时表`
1.主节点有逻辑错误
2.在向临时表中插入数据完成复制并清空临时表的事件之后,且在调用查询并向主表插入数据的存储过程之前,重启服务器。因此,从服务器仅是重新创建一个空的临时表并且没有插入任何数据。(主从动作不一致)

5 慢查询

1.调优查询本身
2.调优表(加索引)
3.调优服务器

6 构建测试数据

#开启GTID之后不支持
insert into t1 select * from t2;#可限制插入字段,多执行几次,数据量就有了

7 查询Handler_%

通过在查询计划前后查询Handler_%的状态可以检查是否使用了索引:
show status like 'Handler_%'; #为当前会话,在测试前请使用flush status 重置这些变量
root@localhost[(none)]> show status like 'Handler_%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Handler_commit             | 0     |
| Handler_delete             | 0     |
| Handler_discover           | 0     |
| Handler_external_lock      | 0     |
| Handler_mrr_init           | 0     |
| Handler_prepare            | 0     |
| Handler_read_first         | 0     |
| Handler_read_key           | 0     |
| Handler_read_last          | 0     |
| Handler_read_next          | 0     |
| Handler_read_prev          | 0     |
| Handler_read_rnd           | 0     |
| Handler_read_rnd_next      | 0     |
| Handler_rollback           | 0     |
| Handler_savepoint          | 0     |
| Handler_savepoint_rollback | 0     |
| Handler_update             | 0     |
| Handler_write              | 0     |
+----------------------------+-------+
Handler_read_rnd_next 值过高,代表从datafile中读取下一个值的频率就越高。一般代表全表扫描,影响性能。
Handler_read_key 表示读取索引的请求数目,相对于Handler_read_rnd_next差值不应该过多。过多说明没有使用到索引。
Handler_commit 事物提交次数 和Handler_read_first 读索引中第一项的次数(值为1,表示全索引扫描,只读取了一次)

8 日志

mysqld got signal 11;
表明mysql向操作系统申请资源(访问文件,或是内存)后终止了。代表分段错误。

9 表损坏

MyiSAM  .frm   .myd  .myi

关键字:repair或crashed 表示表损坏

1.
check table tablename;  #验证是否损坏了
repair table tablename;  #修复

极端情况,repair table extended 执行速度比 repair table 慢,但是可以修复99%的问题。
更极端的情况,repair table use_frm tablename;  他会不相信索引文件的信息,通过.frm文件重建索引。

2.myisamchk ,服务关闭之后修复,或是flush tables+lock table table_name write;之后执行。最好不要访问表。

3.mysqlcheck-->check+repair 支持 --all-databases,可远程


InnoDB 
在共享表空间中存储数据和索引。就算是使用独立表空间,表定义仍然在共享表空间中。

1. 
启动时,会自动修复。如果数据损坏的很严重,需要人为。

2.--innodb_force_recovery 启动项。0-6,0为不强制修复,1是最低级别,6最高。推荐从1开始增加,尝试启动服务。
启动成功之后,通过select into outfile 将表转储到文件中,然后使用drop和create 命令重新创建表。
最后使用innodb_force_recovery=0 重新启动服务,加载转储的数据文件。
循环以上,直到修复所有表。

10 并发

表锁,行锁,页锁,元数据锁。 其中页锁存在于BDB存储引擎中。
`元数据是DDL语句的更改信息,create drop,alter,cruncate等`
lock table .. read
lock table .. write

1.show processlist;

表锁,像myisam 会阻塞其他连接对相同表的更新

行锁,innodb 会阻塞其他连接对相同行的更新(innodb_lock_wait_timeout默认50s)
update t set a=sleep(200) where; #带有等待时间的更新语句

`where条件是主键或是唯一键可以减少锁,增加并发`

`监控器 show engine innodb status\G`

#I_S库的数据都是内存信息,当前信息。
`I_S.processlist表` where time >50

#以下两个表在高版本中将移除。8.0 ,5.7还有。
`I_S.innodb_locks`  是否有锁等待
`I_S.innodb_lock_waits` 保存已获取锁和等待锁的信息
requesting_trx_id  被阻塞的事物ID
blocking_trx_id   持有锁的事物ID

requested_lock_id 被请求的锁信息
blocking_lock_id  持有锁的信息

`I_S.innodb_trx` 可以帮我们找到需要kill 的 trx_mysql_thread_id,可以通过show processlist再次确认。一般是kill持有锁的ID

11 死锁

死锁是指当两个或是多个竞争事务彼此等待对方释放锁,从而导致事务永远无法终止的情况。
`在行锁级别,死锁是无法100%避免的`

死锁探测器会自动回滚一个事务,成功执行另个事务。

show engine innodb status\G 可以看到最近的一次死锁,可能会被覆盖
waiting for this lock to be granted 相关部分,表示事务在等待哪个锁
holds the locks 相关部分,表示阻塞事务的锁的信息

一般来说,DDL语句和事务相关的语句和管理语句会产生隐式提交。#在事务中隐式提交会提交执行之前的语句,如create table 会提交insert,语句顺序,begin,insert,create table,rollback;

12 元数据锁

metadata lock  又称DML锁
为保证数据一致性,在其他事务使用表的情况下,对表的DDL操作应该阻塞。MySQL版本>5.5.3

`在事务开始的时候,他会获取所有需要使用的表上的元数据锁,并在事务结束后释放。其他需要修改这些表定义的线程都需要等待事务结束`

lock_wait_timeout 默认值是1年,可以设置为1s.更快的返回错误提示。

13 hang

1.show processlist; 看Time ,state,info
2.show engine innodb status\G  看transactions部分
3.
`P_S.mutex_instances`  #该表会列出自服务器启动以来所有的冲突。
desc mutex_instances;
+-----------------------+---------------------+------+-----+---------+-------+
| Field                 | Type                | Null | Key | Default | Extra |
+-----------------------+---------------------+------+-----+---------+-------+
| NAME                  | varchar(128)        | NO   |     | NULL    |       |
| OBJECT_INSTANCE_BEGIN | bigint(20) unsigned | NO   |     | NULL    |       |
| LOCKED_BY_THREAD_ID   | bigint(20) unsigned | YES  |     | NULL    |       |
+-----------------------+---------------------+------+-----+---------+-------+

`select * from mutex_instances where LOCKED_BY_THREAD_ID is not null\G

#要查出谁在等待这些冲突,可以查询events_waits_current表

select THREAD_ID,EVENT_NAME,SOURCE,TIMER_START,OBJECT_INSTANCE_BEGIN,OPERATION from events_waits_current where THREAD_ID in (select LOCKED_BY_THREAD_ID from mutex_instances where LOCKED_BY_THREAD_ID is not null)\G

注意THREAD_ID不是连接线程的id,不能kill

可以通过theads表找到连接线程的id,字段名为  PROCESSLIST_ID

14 复制

基于语句的复制,更容易造成主从数据不一致,如,对没有非唯一约束的表更新
推荐基于row的格式记录日志(日志中记录原始数据)

基于语句格式(日志中记录原始的sql)

事务只会在提交之后在日志中写入数据。

一个事务中,包含事务表和非事务表,回滚和崩溃时,也容易造成主从数据不一致。

15 sql_mode

strict_trans_tables ,严格模式

16 Max_allowed_packet

`限制服务器和客户端之间传递的单个数据包的字节数
`大表或是blob类型`

show variables like '%max_allowed%';
+--------------------------+------------+
| Variable_name            | Value      |
+--------------------------+------------+
| max_allowed_packet       | 67108864   |

select repeat('a',67108865); #超过了阈值
+----------------------+
| repeat('a',67108865) |
+----------------------+
| NULL                 |
+----------------------+
1 row in set, 1 warning (0.00 sec)

show warnings;

| Warning | 1301 | Result of repeat() was larger than max_allowed_packet (67108864) - truncated |

17 secure_file_priv

限制load file 函数 load data 和select  into  outfile 语句只能使用指定目录

18 open_files_limit

允许打开的文件数,如果值过小,会出现无法建立新连接。和操作系统和用户设置有关ulimit -n,和启动脚本有关。 cat /proc/pid/limits 查看软硬连接可打开的文件数。

19 服务器启动时设置core选择来获得一个核心文件

#核心文件包含一个进程的内存映像,当进程意外终止时会创建它
gdb core.222

load data 和select into outfile 语句只能使用指定目录


## 18 open_files_limit

```shell
允许打开的文件数,如果值过小,会出现无法建立新连接。和操作系统和用户设置有关ulimit -n,和启动脚本有关。 cat /proc/pid/limits 查看软硬连接可打开的文件数。

19 服务器启动时设置core选择来获得一个核心文件

#核心文件包含一个进程的内存映像,当进程意外终止时会创建它
gdb core.222

–[美] Sveta Smirnova 著

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值