myawr布置
Posted magicaltravel
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了myawr布置相关的知识,希望对你有一定的参考价值。
实现功能:
类似于osw,收集mysql线程以及锁等待的状态,和osw不同的是,myawr是嵌入到mysql里面去的,要使用该功能,需要打开事件 set global event_scheduler = on;
其中收集日志的表使用自建分区,并且会自动drop掉7天以前的分区。
create database myawr DEFAULT CHARACTER SET utf8; use myawr; CREATE TABLE myawr.`processliststatus` ( `ID` bigint(21) unsigned NOT NULL DEFAULT ‘0‘, `USER` varchar(32) NOT NULL DEFAULT ‘‘, `HOST` varchar(64) NOT NULL DEFAULT ‘‘, `DB` varchar(64) DEFAULT NULL, `COMMAND` varchar(16) NOT NULL DEFAULT ‘‘, `TIME` int(7) NOT NULL DEFAULT ‘0‘, `STATE` varchar(64) DEFAULT NULL, `INFO` longtext, `clock` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `snapid` bigint(20) DEFAULT NULL, KEY `idx_clock` (`clock`), key idx_snapid(snapid) ); CREATE TABLE myawr.`mysqldumplog` ( `ID` bigint(21) unsigned NOT NULL DEFAULT ‘0‘, `USER` varchar(32) NOT NULL DEFAULT ‘‘, `HOST` varchar(64) NOT NULL DEFAULT ‘‘, `DB` varchar(64) DEFAULT NULL, `COMMAND` varchar(16) NOT NULL DEFAULT ‘‘, `TIME` int(7) NOT NULL DEFAULT ‘0‘, `STATE` varchar(64) DEFAULT NULL, `INFO` longtext, `clock` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, KEY `idx_clock` (`clock`) ); CREATE TABLE myawr.`lockstatus` ( `clock` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `wating_trx_state` varchar(255) DEFAULT NULL, `waiting_trx_id` bigint(20) DEFAULT NULL, `waiting_thread` int(11) DEFAULT NULL, `waiting_query` varchar(2000) DEFAULT NULL, `blocking_trx_state` varchar(255) DEFAULT NULL, `blocking_trx_id` bigint(20) DEFAULT NULL, `blocking_thread` int(11) DEFAULT NULL, `blocking_query` varchar(2000) DEFAULT NULL, `snapid` bigint(20) DEFAULT NULL, KEY `idx_clock` (`clock`), key idx_snapid(snapid) ); DELIMITER $$ CREATE PROCEDURE myawr.`partition_verify`(SCHEMANAME VARCHAR(64), TABLENAME VARCHAR(64), HOURLYINTERVAL INT(11)) BEGIN DECLARE PARTITION_NAME VARCHAR(16); DECLARE RETROWS INT(11); DECLARE FUTURE_TIMESTAMP TIMESTAMP; SELECT COUNT(1) INTO RETROWS FROM information_schema.partitions WHERE table_schema = SCHEMANAME AND table_name = TABLENAME AND partition_name IS NULL; IF RETROWS = 1 THEN SET FUTURE_TIMESTAMP = TIMESTAMPADD(HOUR, HOURLYINTERVAL, CONCAT(CURDATE(), " ", ‘00:00:00‘)); SET PARTITION_NAME = DATE_FORMAT(CURDATE(), ‘p%Y%m%d%H00‘); -- Create the partitioning query SET @__PARTITION_SQL = CONCAT("ALTER TABLE ", SCHEMANAME, ".", TABLENAME, " PARTITION BY RANGE(UNIX_TIMESTAMP(`clock`))"); SET @__PARTITION_SQL = CONCAT(@__PARTITION_SQL, "(PARTITION ", PARTITION_NAME, " VALUES LESS THAN (", UNIX_TIMESTAMP(FUTURE_TIMESTAMP), "));"); -- Run the partitioning query PREPARE STMT FROM @__PARTITION_SQL; EXECUTE STMT; DEALLOCATE PREPARE STMT; END IF; END $$ CREATE PROCEDURE myawr.`partition_create` ( SCHEMANAME VARCHAR ( 64 ), TABLENAME VARCHAR ( 64 ), PARTITIONNAME VARCHAR ( 64 ), CLOCK INT ) BEGIN DECLARE RETROWS INT; SELECT COUNT( 1 ) INTO RETROWS FROM information_schema.PARTITIONS WHERE table_schema = SCHEMANAME AND table_name = TABLENAME AND partition_description >= CLOCK; IF RETROWS = 0 THEN SELECT CONCAT( "partition_create(", SCHEMANAME, ",", TABLENAME, ",", PARTITIONNAME, ",", CLOCK, ")" ) AS msg; SET @SQL = CONCAT( ‘ALTER TABLE ‘, SCHEMANAME, ‘.‘, TABLENAME, ‘ ADD PARTITION (PARTITION ‘, PARTITIONNAME, ‘ VALUES LESS THAN (‘, CLOCK, ‘));‘ ); PREPARE STMT FROM @SQL; EXECUTE STMT; DEALLOCATE PREPARE STMT; END IF; END $$ CREATE PROCEDURE myawr.`partition_drop` ( SCHEMANAME VARCHAR ( 64 ), TABLENAME VARCHAR ( 64 ), DELETE_BELOW_PARTITION_DATE BIGINT ) BEGIN DECLARE done INT DEFAULT FALSE; DECLARE drop_part_name VARCHAR ( 16 ); DECLARE myCursor CURSOR FOR SELECT partition_name FROM information_schema.PARTITIONS WHERE table_schema = SCHEMANAME AND table_name = TABLENAME AND CAST( SUBSTRING( partition_name FROM 2 ) AS UNSIGNED ) < DELETE_BELOW_PARTITION_DATE; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; SET @alter_header = CONCAT( "ALTER TABLE ", SCHEMANAME, ".", TABLENAME, " DROP PARTITION " ); SET @drop_partitions = ""; OPEN myCursor; read_loop : LOOP FETCH myCursor INTO drop_part_name; IF done THEN LEAVE read_loop; END IF; SET @drop_partitions = IF ( @drop_partitions = "", drop_part_name, CONCAT( @drop_partitions, ",", drop_part_name ) ); END LOOP; IF @drop_partitions != "" THEN SET @full_sql = CONCAT( @alter_header, @drop_partitions, ";" ); PREPARE STMT FROM @full_sql; EXECUTE STMT; DEALLOCATE PREPARE STMT; SELECT CONCAT( SCHEMANAME, ".", TABLENAME ) AS `table`, @drop_partitions AS `partitions_deleted`; ELSE SELECT CONCAT( SCHEMANAME, ".", TABLENAME ) AS `table`, "N/A" AS `partitions_deleted`; END IF; END $$ CREATE PROCEDURE myawr.`partition_maintenance`(SCHEMA_NAME VARCHAR(32), TABLE_NAME VARCHAR(32), KEEP_DATA_DAYS INT, HOURLY_INTERVAL INT, CREATE_NEXT_INTERVALS INT) BEGIN DECLARE OLDER_THAN_PARTITION_DATE VARCHAR(16); DECLARE PARTITION_NAME VARCHAR(16); DECLARE OLD_PARTITION_NAME VARCHAR(16); DECLARE LESS_THAN_TIMESTAMP INT; DECLARE CUR_TIME INT; CALL partition_verify(SCHEMA_NAME, TABLE_NAME, HOURLY_INTERVAL); SET CUR_TIME = UNIX_TIMESTAMP(DATE_FORMAT(NOW(), ‘%Y-%m-%d 00:00:00‘)); SET @__interval = 1; create_loop: LOOP IF @__interval > CREATE_NEXT_INTERVALS THEN LEAVE create_loop; END IF; SET LESS_THAN_TIMESTAMP = CUR_TIME + (HOURLY_INTERVAL * @__interval * 3600); SET PARTITION_NAME = FROM_UNIXTIME(CUR_TIME + HOURLY_INTERVAL * (@__interval - 1) * 3600, ‘p%Y%m%d%H00‘); IF(PARTITION_NAME != OLD_PARTITION_NAME) THEN CALL partition_create(SCHEMA_NAME, TABLE_NAME, PARTITION_NAME, LESS_THAN_TIMESTAMP); END IF; SET @[email protected]__interval+1; SET OLD_PARTITION_NAME = PARTITION_NAME; END LOOP; SET OLDER_THAN_PARTITION_DATE=DATE_FORMAT(DATE_SUB(NOW(), INTERVAL KEEP_DATA_DAYS DAY), ‘%Y%m%d0000‘); CALL partition_drop(SCHEMA_NAME, TABLE_NAME, OLDER_THAN_PARTITION_DATE); END$$ CREATE PROCEDURE myawr.proc_awr_killdump( ) BEGIN declare dump_id INT default false; DECLARE done INT DEFAULT FALSE; DECLARE myCursor CURSOR FOR SELECT id FROM information_schema.PROCESSLIST WHERE INFO like ‘SELECT /*!40001 SQL_NO_CACHE */ * FROM%‘; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; SET @dump_id =‘‘; OPEN myCursor; read_loop : LOOP FETCH myCursor INTO dump_id; IF done THEN LEAVE read_loop; END IF; insert into myawr.mysqldumplog(ID,USER,HOST,DB,COMMAND,TIME,STATE,INFO) select ID,USER,HOST,DB,COMMAND,TIME,STATE,INFO from information_schema.processlist where id=dump_id; call mysql.rds_kill(dump_id); END LOOP; END $$ CREATE procedure myawr.proc_awr_getstatus() begin declare insertSessionCount INT default 0; -- 声明insert会话的计数器 set @ha=unix_timestamp(now()); -- 查看是否有insert 会话 select count(*) into insertSessionCount from information_schema.processlist where INFO like ‘insert into myawr.processliststatus%‘; -- 如果之前存在未结束的insert会话,则本次不insert IF insertSessionCount <1 THEN -- 排除非活跃会话和系统会话,并做截断操作 insert into myawr.processliststatus(ID,USER,HOST,DB,COMMAND,TIME,STATE,INFO,snapid) select ID,USER,HOST,DB,COMMAND,TIME,STATE,substring(INFO,1,3000), @ha from information_schema.processlist where COMMAND not in (‘Sleep‘,‘Daemon‘,‘Binlog Dump GTID‘) and INFO not like ‘insert into myawr.processliststatus%‘; END IF; insert into myawr.lockstatus(wating_trx_state,waiting_trx_id,waiting_thread,waiting_query,blocking_trx_state,blocking_trx_id,blocking_thread,blocking_query,snapid) SELECT r.trx_state wating_trx_state,r.trx_id waiting_trx_id,r.trx_mysql_thread_Id waiting_thread,r.trx_query waiting_query,b.trx_state blocking_trx_state,b.trx_id blocking_trx_id,b.trx_mysql_thread_id blocking_thread,b.trx_query blocking_query,@ha FROM information_schema.innodb_lock_waits w INNER JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id INNER JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id; end $$ create event myawr.event_awr_resetpartition ON SCHEDULE every 1 day on completion preserve do begin call partition_maintenance(‘myawr‘,‘processliststatus‘,7,24,30); call partition_maintenance(‘myawr‘,‘lockstatus‘,7,24,30); end $$ create procedure myawr.proc_awr_enable(proc_name varchar(64)) begin if proc_name = ‘all‘ then select "抱歉,该参数现在还没能实现,敬请期待" as msg; elseif proc_name = ‘killdump‘ then alter event event_awr_killdump enable; select "enable event_awr_killdump succeed ~" as msg; elseif proc_name = ‘getmysqlstatus‘ then alter event event_awr_getMysqlStatus enable; select "enable event_awr_getMysqlStatus succeed ~" as msg; else select "参量输入有误抑或没有布置awr脚本!" as msg; end if; end $$ create procedure myawr.proc_awr_disable(proc_name varchar(64)) begin if proc_name = ‘all‘ then select "抱歉,该参数现在还没能实现,敬请期待" as msg; elseif proc_name = ‘killdump‘ then alter event event_awr_killdump disable; select "disable event_awr_killdump succeed ~" as msg; elseif proc_name = ‘getmysqlstatus‘ then alter event event_awr_getMysqlStatus disable; select "disable event event_awr_getMysqlStatus succeed ~" as msg; else select "参量输入有误抑或没有布置awr脚本!" as msg; end if; end $$ CREATE PROCEDURE myawr.myawr_help() BEGIN select " 1、实现功能: 1.1、默认每10s会收集一次mysql的processlist状态和锁等待情况。 1.2、默认每9s检查是否存在dump操作,如果存在将会kill线程,并且将此记录在mysqldump_log表中。 2、更改参数: 2.1、修改脚本收集或检查的频率 最小时间不应该小于7s,否则可能会对数据库性能产生影响。 mysql> call proc_awr_changeint(‘killdump‘,5); 2.2、启用或停止脚本部分功能 mysql> call proc_awr_enable(‘all‘); mysql> call proc_awr_enable(‘killdump‘); mysql> call proc_awr_enable(‘getmysqlstatus‘); mysql> call proc_awr_disable(‘all‘); mysql> call proc_awr_disable(‘killdump‘); mysql> call proc_awr_disable(‘getmysqlstatus‘); 3、dump操作: 3.1、停止非法dump监控事件 mysql> call proc_awr_disable(‘killdump‘); 4.2、进行dump操作 mysqldump --single-transaction *** 3.3、恢复监控事件 mysql> call proc_awr_enable(‘killdump‘);" AS help_message; end $$ create event myawr.event_awr_getMysqlStatus ON SCHEDULE -- 每隔10秒运行 every 10 second on completion preserve do call proc_awr_getstatus(); $$ CREATE EVENT myawr.event_awr_killdump ON SCHEDULE -- 每隔9秒运行 EVERY 9 SECOND ON COMPLETION PRESERVE DO CALL proc_awr_killdump (); $$ delimiter ; ###############分割线############################### show variables like ‘event_scheduler‘; set global event_scheduler = on; call myawr.proc_awr_enable(‘getmysqlstatus‘); call myawr.proc_awr_disable(‘killdump‘); -- 云上启用该功能 -- event_scheduler=1 #写入/etc/my.cnf
以上是关于myawr布置的主要内容,如果未能解决你的问题,请参考以下文章