数据库CPU打高消耗过大一般来说主要有两点原因:
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,控制并发等。
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;
根据实际情况进行处理。
MySQL
网络延迟:减小副本集节点之间的网络延迟。
磁盘吞吐量:保证磁盘吞吐。
查看show slave status;
通过以上指标判断主从状态以及复制延迟,如果出现较大延迟,可以从以下几个方面考虑:
根据复制中断做出相应调整,如果难以修复,建议重建从库
##传统复制##
#停止复制
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 ;
使用binlog2sql/myflash/脚本方式通过binlog做数据闪回恢复
建立延迟从库,基于全备+增备+binlog
SELECT event_name,current_alloc FROM sys.memory_global_by_current_bytes WHERE event_name LIKE 'memory%innodb%';
通过错误日志排查,具体问题具体分析。
正常来讲,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,启动数据库时,忽略与恢复相关的前滚日志