MySQL 各类场景的故障恢复概要(持续更新)

文章目录

    • 一、CPU打高
    • 二、IOPS打高
    • 三、活跃连接数打高
    • 四、磁盘打高/满
    • 五、复制故障
      • 5.1 复制延迟
      • 5.2 复制中断
    • 六、数据丢失
      • 6.1 DML误操作
      • 6.2 DDL误操作
    • 七、其他场景
      • 7.1 OOM排查
      • 7.2 数据库无法启动
      • 7.3 数据库坏页

一、CPU打高

数据库CPU打高消耗过大一般来说主要有两点原因:

  • 慢SQL
      慢sql导致,比如说全表扫描、扫描数据量太大,排序操作,锁争用等。
    使用explain,profile进行优化
  • QPS高
      大量并发导致资源紧张。

OS
  首先通过top查看系统CPU使用率情况,是否是MySQL导致。如果是云上RDS可忽略,直接查看RDS实例CPU使用率即可

MySQL
查看QPS

show global status like 'Question%';

查看活跃会话

select * from information_schema.processlist where command!='Sleep';

查看逻辑读

show global status like 'innodb_buffer_pool_read_requests';

查看临时表情况

show status like 'Create_tmp%';

查看锁争用

SHOW STATUS LIKE ‘Innodb_row_lock%’;

引擎各种状态查看

show engine innodb status\G

分析慢日志

mysqldumpslow -s c slow.log>/tmp/slow_report.txt

  根据以上状态值分析CPU打高原因,针对具体问题具体分析。如:优化SQL,控制并发等。

二、IOPS打高

OS
  iostat 和pt-ioprofile查看IO性能,如果是云上RDS可忽略,直接查看RDS实例IOPS即可。

MySQL

查看活跃会话

select * from information_schema.processlist where command!='Sleep';

查看数据库读写压力

SELECT file_name AS file,
    count_read,
    sum_number_of_bytes_read AS total_read,
    count_write,
    sum_number_of_bytes_write AS total_written,
    (sum_number_of_bytes_read + sum_number_of_bytes_write) AS total
 FROM performance_schema.file_summary_by_instance
ORDER BY sum_number_of_bytes_read+ sum_number_of_bytes_write DESC;

查看物理读

show global status like 'Innodb_buffer_pool_reads';

  分析并优化相应SQL。

三、活跃连接数打高

  通过监控查看活跃连接数以及其他数据库资源问题,确定是由于大量活跃连接导致数据库资源打满还是资源打满导致活跃连接堆积。

MySQL

查看当前活跃会话

select * from information_schema.processlist where command!='Sleep';

  如果是大量高效SQL并发导致的问题,需要从业务上定位;如果是低效SQL导致资源紧张,则需要根据活跃会话以及慢日志进行优化,临时解决可以通过kill会话处理。

四、磁盘打高/满


OS

查看磁盘空间

df -TH

查看innode用量

df -iH

MySQL

查看binlog占用空间

show master logs;

查看表大小

SELECT table_schema as `Database`, table_name AS `Table`, round(((data_length + index_length) / 1024 / 1024 / 1024), 2) `Size in GB` FROM information_schema.TABLES where table_schema = 'test' ORDER BY (data_length + index_length) DESC ;

查看临时表空间大小

select * from INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO;

碎片查看

SELECT CONCAT(table_schema, '.', table_name)                    AS  TABLE_NAME
      ,engine                                                   AS  TABLE_ENGINE 
      ,table_type                                               AS  TABLE_TYPE
      ,table_rows                                               AS  TABLE_ROWS
      ,CONCAT(ROUND(data_length  / ( 1024 * 1024), 2), 'M')     AS  TB_DATA_SIZE 
      ,CONCAT(ROUND(index_length / ( 1024 * 1024), 2), 'M')     AS  TB_IDX_SIZE 
      ,CONCAT(ROUND((data_length + index_length ) 
            / ( 1024 * 1024 ), 2), 'M')                         AS  TOTAL_SIZE
      ,CASE WHEN  data_length =0 THEN 0
            ELSE  ROUND(index_length / data_length, 2) END      AS  TB_INDX_RATE
    ,CONCAT(ROUND( data_free / 1024 / 1024,2), 'MB')            AS  TB_DATA_FREE 
    ,CASE WHEN (data_length + index_length) = 0 THEN 0
             ELSE ROUND(data_free/(data_length + index_length),2) 
     END                                                        AS  TB_FRAG_RATE
FROM information_schema.TABLES  
ORDER BY data_free DESC;
#重建表空间
optimize table tablename;

  根据实际情况进行处理。

五、复制故障

5.1 复制延迟

MySQL
网络延迟:减小副本集节点之间的网络延迟。
磁盘吞吐量:保证磁盘吞吐。
查看show slave status;
MySQL 各类场景的故障恢复概要(持续更新)_第1张图片

通过以上指标判断主从状态以及复制延迟,如果出现较大延迟,可以从以下几个方面考虑:

  • 大事物延迟,避免大事务
  • 大表DDL延迟,可能存在MDL锁阻塞,kill掉阻塞源
  • 长期未提交的事物延迟,杜绝长事务
  • 表上没有主键或者唯一键,可以通过slave_rows_search_algorithms变量一定程度优化,建议所有业务表均建立主键
  • Innodb层锁造成延迟,分析锁关系,做出相应处理

5.2 复制中断

根据复制中断做出相应调整,如果难以修复,建议重建从库

##传统复制##
#停止复制
mysql>stop slave;
#设定跳过一个事务
mysql>SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1
#重新开启复制
mysql>start slave;
#这样就正常了,但是,当然还是要把数据修改上去
mysql>update tables set ... where;
##GTID##
#停止复制
mysql>stop slave;
#然后执行设置一个事务GTID来跳过,就是要跳过这个事务的意思
mysql>SET gtid_next = '2a4aaa93-98e4-11ea-b9b2-00163e0c8a51:1-8';
#注入空事务
mysql>BEGIN;COMMIT;
#把GTID设置回自动模式
mysql>SET gtid_next = 'AUTOMATIC';
#重新开启复制
mysql>START SLAVE;
#当然跳过了,并不代表这个数据就不修改了,还是要你手动去修改一下,这样就一切回归正常了
mysql>update tables set ...;

#停止复制
mysql>stop slave;
#直接设置上面的GTID值+1
mysql>SET @@GLOBAL.GTID_PURGED='2a4aaa93-98e4-11ea-b9b2-00163e0c8a51:1-8';
#重新开启复制
mysql>START SLAVE;
#当然跳过了,并不代表这个数据就不修改了,还是要你手动去修改一下,这样就一切回归正常了
mysql>update tables set ...;

##传统模式##
#停止复制
mysql>stop slave;
#设定跳过一个事务
mysql>SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1
#重新开启复制
mysql>start slave;
#这样就正常了,但是,当然还是要把数据修改上去
mysql>update tables set ... where ;

六、数据丢失

6.1 DML误操作

使用binlog2sql/myflash/脚本方式通过binlog做数据闪回恢复

6.2 DDL误操作

建立延迟从库,基于全备+增备+binlog

七、其他场景

7.1 OOM排查

SELECT event_name,current_alloc FROM sys.memory_global_by_current_bytes WHERE event_name LIKE 'memory%innodb%';

7.2 数据库无法启动

通过错误日志排查,具体问题具体分析。

7.3 数据库坏页

正常来讲,innodb_force_recovery=1即可,然后逻辑导出。

innodb_force_recovery=1,即使发现了损坏页面也继续让服务器继续运行,这个选项对于备份或者转存当前数据尤为有用
innodb_force_recovery=2,阻止恢复主线程的运行,如果清除操作会导致服务器挂掉
innodb_force_recovery=3,恢复后不回滚事务
innodb_force_recovery=4,如果插入到缓冲区的合并操作会导致系统崩溃,将不会被执行
innodb_force_recovery=5,启动数据库时,忽略撤消日志
innodb_force_recovery=6,启动数据库时,忽略与恢复相关的前滚日志

你可能感兴趣的:(MySQL)