zoukankan      html  css  js  c++  java
  • mysql sql语句统计查询

    环境是mysql8.0

    之前调研过mysql audit 插件,均没有发现能适合mysql8.0环境的,除了企业版mysql审计插件,于是想了一个办法,把mysql慢日志时间改为0,这样所有sql都会被记录到慢日志里面,然后在用pt工具解析,过滤,然后写入到数据库。

    my.cnf慢日志配置:

    slow_query_log_file = /database/mysql/mysql-slow.log
    slow_query_log = 1
    log_slow_extra=1
    long_query_time=0
    log_slow_admin_statements=1
    log_slow_slave_statements=1

    pt-query-digest脚本:

    #!/bin/bash
    ## ==================================================================================
    ##    让读书成为一种生活方式。就像吃喝拉撒每天必须要干的事,
    ## 终有一天你的举止、言谈、气质会不一样。 
    ##                                        —- async 
    ##
    ## Created Date: Sunday, 2020-05-16, 3:48:04 pm
    ## copyright (c):    SZWW Tech. LTD. 
    ## Engineer:   async 
    ## Module Name:   
    ## Revision:   v0.01 
    ## Description:
    ##   
    ## Revision History : 
    ## Revision     editor         date         Description         
    ## v0.01        async          2020-05-16   File Created
    ## ==================================================================================
    DIR="$( cd "$( dirname "$0"  )" && pwd  )"
    cd $DIR
    dt=`date --date='5 min ago' "+%Y-%m-%d %H:%M:%S"`
    #配置数据库的连接地址
    monitor_db_host="172.18.1.xx"
    monitor_db_port=33601
    monitor_db_user="xxxxx"
    monitor_db_password="xxxxx"
    monitor_db_database="xxxx"
    dba="xxxxx"
    #实例慢日志位置
    slowquery_file=/database/mysql/mysql-slow.log
    pt_query_digest="/usr/bin/pt-query-digest"
    #实例连接信息
    hostname="`hostname`" # 和实例配置内容保持一致,用于做筛选
    
    #获取上次分析时间,初始化时请删除last_analysis_time_$hostname文件,可分析全部日志数据
    if [ -s ddl_last_analysis_time_$hostname ]; then
        last_analysis_time=`cat ddl_last_analysis_time_$hostname`
    else
        last_analysis_time='1000-01-01 00:00:00'
    fi
    
    #收集日志
    /usr/bin/cat $slowquery_file|grep -vE 'gtid_executed_v3|java' >/database/slow_log/mysql_slow.log && 
    $pt_query_digest 
    --user=$monitor_db_user --password=$monitor_db_password --port=$monitor_db_port 
    --history h=$monitor_db_host,D=$monitor_db_database,t=review_history  
    --no-report --limit=100% --charset=utf8mb4 
    --filter="$event->{add_column}=length($event->{arg}) and $event->{fingerprint}=~ m/^(create|alter|drop|rename|truncate|comment)/i 
    and $event->{client}=$event->{ip}" /database/slow_log/mysql_slow.log > /tmp/analysis_slow_query.log
    if [ $? -ne 0 ]; then
    echo "failed"|/usr/bin/mailx -s "$0 failed on $(hostname) at $(date) " ${dba}
    else
    echo `date +"%Y-%m-%d %H:%M:%S"`> ddl_last_analysis_time_$hostname
    fi

    我的日志里面有一些错误格式的日志,所以我把gtid_executed_v3这种过滤掉了,然后过滤出ddl ~ m/^(create|alter|drop|rename|truncate|comment)/i ,过滤dml为 ~ m/^(update|insert|delete)/i ,我主要过滤我关注的几类,然后写入表 review_history 

    review_history建表语句:

    CREATE TABLE review_history (
      id int(11) NOT NULL AUTO_INCREMENT,
      hostname_max varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_as_cs DEFAULT NULL,
      client_max varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_as_cs DEFAULT NULL,
      user_max varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_as_cs DEFAULT NULL,
      db_max varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_as_cs DEFAULT NULL,
      checksum char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_as_cs DEFAULT NULL,
      sample longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_as_cs,
      ts_min timestamp NULL DEFAULT NULL,
      ts_max timestamp NULL DEFAULT NULL,
      ts_cnt float DEFAULT NULL,
      Query_time_sum float DEFAULT NULL,
      Query_time_min float DEFAULT NULL,
      Query_time_max float DEFAULT NULL,
      Query_time_pct_95 float DEFAULT NULL,
      Query_time_stddev float DEFAULT NULL,
      Query_time_median float DEFAULT NULL,
      Lock_time_sum float DEFAULT NULL,
      Lock_time_min float DEFAULT NULL,
      Lock_time_max float DEFAULT NULL,
      Lock_time_pct_95 float DEFAULT NULL,
      Lock_time_stddev float DEFAULT NULL,
      Lock_time_median float DEFAULT NULL,
      Rows_sent_sum float DEFAULT NULL,
      Rows_sent_min float DEFAULT NULL,
      Rows_sent_max float DEFAULT NULL,
      Rows_sent_pct_95 float DEFAULT NULL,
      Rows_sent_stddev float DEFAULT NULL,
      Rows_sent_median float DEFAULT NULL,
      Rows_examined_sum float DEFAULT NULL,
      Rows_examined_min float DEFAULT NULL,
      Rows_examined_max float DEFAULT NULL,
      Rows_examined_pct_95 float DEFAULT NULL,
      Rows_examined_stddev float DEFAULT NULL,
      Rows_examined_median float DEFAULT NULL,
      Rows_affected_sum float DEFAULT NULL,
      Rows_affected_min float DEFAULT NULL,
      Rows_affected_max float DEFAULT NULL,
      Rows_affected_pct_95 float DEFAULT NULL,
      Rows_affected_stddev float DEFAULT NULL,
      Rows_affected_median float DEFAULT NULL,
      Rows_read_sum float DEFAULT NULL,
      Rows_read_min float DEFAULT NULL,
      Rows_read_max float DEFAULT NULL,
      Rows_read_pct_95 float DEFAULT NULL,
      Rows_read_stddev float DEFAULT NULL,
      Rows_read_median float DEFAULT NULL,
      Merge_passes_sum float DEFAULT NULL,
      Merge_passes_min float DEFAULT NULL,
      Merge_passes_max float DEFAULT NULL,
      Merge_passes_pct_95 float DEFAULT NULL,
      Merge_passes_stddev float DEFAULT NULL,
      Merge_passes_median float DEFAULT NULL,
      InnoDB_IO_r_ops_min float DEFAULT NULL,
      InnoDB_IO_r_ops_max float DEFAULT NULL,
      InnoDB_IO_r_ops_pct_95 float DEFAULT NULL,
      InnoDB_IO_r_ops_stddev float DEFAULT NULL,
      InnoDB_IO_r_ops_median float DEFAULT NULL,
      InnoDB_IO_r_bytes_min float DEFAULT NULL,
      InnoDB_IO_r_bytes_max float DEFAULT NULL,
      InnoDB_IO_r_bytes_pct_95 float DEFAULT NULL,
      InnoDB_IO_r_bytes_stddev float DEFAULT NULL,
      InnoDB_IO_r_bytes_median float DEFAULT NULL,
      InnoDB_IO_r_wait_min float DEFAULT NULL,
      InnoDB_IO_r_wait_max float DEFAULT NULL,
      InnoDB_IO_r_wait_pct_95 float DEFAULT NULL,
      InnoDB_IO_r_wait_stddev float DEFAULT NULL,
      InnoDB_IO_r_wait_median float DEFAULT NULL,
      InnoDB_rec_lock_wait_min float DEFAULT NULL,
      InnoDB_rec_lock_wait_max float DEFAULT NULL,
      InnoDB_rec_lock_wait_pct_95 float DEFAULT NULL,
      InnoDB_rec_lock_wait_stddev float DEFAULT NULL,
      InnoDB_rec_lock_wait_median float DEFAULT NULL,
      InnoDB_queue_wait_min float DEFAULT NULL,
      InnoDB_queue_wait_max float DEFAULT NULL,
      InnoDB_queue_wait_pct_95 float DEFAULT NULL,
      InnoDB_queue_wait_stddev float DEFAULT NULL,
      InnoDB_queue_wait_median float DEFAULT NULL,
      InnoDB_pages_distinct_min float DEFAULT NULL,
      InnoDB_pages_distinct_max float DEFAULT NULL,
      InnoDB_pages_distinct_pct_95 float DEFAULT NULL,
      InnoDB_pages_distinct_stddev float DEFAULT NULL,
      InnoDB_pages_distinct_median float DEFAULT NULL,
      QC_Hit_cnt float DEFAULT NULL,
      QC_Hit_sum float DEFAULT NULL,
      Full_scan_cnt float DEFAULT NULL,
      Full_scan_sum float DEFAULT NULL,
      Full_join_cnt float DEFAULT NULL,
      Full_join_sum float DEFAULT NULL,
      Tmp_table_cnt float DEFAULT NULL,
      Tmp_table_sum float DEFAULT NULL,
      Tmp_table_on_disk_cnt float DEFAULT NULL,
      Tmp_table_on_disk_sum float DEFAULT NULL,
      Filesort_cnt float DEFAULT NULL,
      Filesort_sum float DEFAULT NULL,
      Filesort_on_disk_cnt float DEFAULT NULL,
      Filesort_on_disk_sum float DEFAULT NULL,
      Bytes_sum float DEFAULT NULL,
      Bytes_min float DEFAULT NULL,
      Bytes_max float DEFAULT NULL,
      Bytes_pct_95 float DEFAULT NULL,
      Bytes_stddev float DEFAULT NULL,
      Bytes_median float DEFAULT NULL,
      PRIMARY KEY (id),
      UNIQUE KEY checksum (checksum,ts_min,ts_max),
      KEY idx_hostname_max_ts_min (hostname_max,ts_min)
    ) ENGINE=InnoDB AUTO_INCREMENT=797 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_as_cs ROW_FORMAT=COMPRESSED

    参考官方链接https://www.percona.com/doc/percona-toolkit/3.0/pt-query-digest.html

    然后加入crontab,每个几分钟执行一次,后来发现这样会漏记录一些sql,频繁去解析slow_log对操作系统io也有一定消耗,思考以后,改成了每隔6小时全量执行一次,这样就会有一点延时,不过这个主要用于审计sql,延时也能接受,如果要实时,在想想办法。不增量以后,没再发现漏记sql。

    主要就是pt的filter参数:

     --filter="$event->{add_column}=length($event->{arg}) and $event->{hostname}="$hostname" and $event->{client}=$event->{ip}"  

    一开始是这样写的,记录的太多,查表筛选的时候慢,于是只过滤了自己需要的类型ddl与dml:

    --filter="$event->{add_column}=length($event->{arg}) and $event->{fingerprint}=~ m/^(create|alter|drop|rename|truncate|comment|delete|insert|update)/i 
    and $event->{client}=$event->{ip}"

    然后修改下脚本就实现了mysql的sql审计,然后再配合init-connect,可以实现比较精准快速的排查问题。

  • 相关阅读:
    php常用函数
    检测到有潜在危险的 Request.Form 值
    未能加载文件或程序集“XXX”或它的一个依赖项,试图加载格式不正确的程序
    尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题
    java基础知识
    .net中excel遇到的一些问题
    easyui验证
    .NET牛人需要了解的问题[转]
    关于easyui遇到的一些问题
    MVC 路由介绍
  • 原文地址:https://www.cnblogs.com/5sdba-notes/p/12905054.html
Copyright © 2011-2022 走看看