小鹏鹏装逼课堂之:统计指定时间段数据库表的操作次数。
处女作,需要大神帮忙优化。


bug修复:

1、小时位为个位数时,时间显示异常 ----- 已修复

#####注:::以下脚本中路径可能需要各位自行进行修改
图片



实现原理:
   1、shell脚本:通过mysqlbinlog将binlog日志文件格式化输出
        定制crontab任务,定时通过向mysql传递show master status查看binlog是否变化,若发生变化则格式化输出已经切换掉的binlog文件
   2、shell脚本:定制crontab任务,通过比对md5码,查看格式化后的binlog文件是否发生改变,若发生改变,则调用python脚本进行统计



A、格式化binlog脚本:脚本名自定

 

#!/bin/bash
# initail progran:
# :echo 111 > /tmp/md5_code.txt     #程序初始化
# :touch /tmp/binlog.dump     #程序初始化
bin_dir='/var/lib/mysql'
md5_record='/tmp/md5_code.txt'
bin_dump='/smbdir/binlog.dump'
sqe_code=`cat ${md5_record}`
md5_bindump=`md5sum $bin_dump|awk '{print $1}'`
zero_fill=`mysql  -e 'show master status' | grep mysql | awk '{print $1}' |grep -o '[0-9]\+' |awk -F'[1-9]' '{print $1}'`
binlog_seq=$((`mysql  -e 'show master status' | grep mysql | awk '{print $1}' |grep -o '[0-9]\+' |  grep -o '[1-9]\+0*$'`-1))
if [ $sqe_code != $binlog_seq ];then
        mysqlbinlog  --base64-output=decode-rows -v $bin_dir/mysql-bin.${zero_fill}${binlog_seq} > $bin_dump
        echo $binlog_seq > $md5_record
fi


B、监控格式化后的binlog脚本:

#!/bin/bash
md5_record='/tmp/md5_code.txt'
bin_dump='/data/smb_sharepath/sup_home/binlog.dump'
md5_code=`cat ${md5_record} |awk '{print $1}'`
local_md5=`md5sum $bin_dump|awk '{print $1}'`
if [ $local_md5 != $md5_code ];then
    /root/scripts/binlog_analyze.py
    echo $local_md5 > $md5_record
fi

C、python统计脚本
####使用此脚本,前提
1、需安装MySQLdb模块
2、创建临时表:

Create Table: CREATE TABLE `operation_count_tmp_table` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `OPERATION` varchar(10) DEFAULT NULL,
  `Database_name` varchar(40) DEFAULT NULL,
  `Table_name` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=410833 DEFAULT CHARSET=utf8

3、创建统计结果表:

Create Table: CREATE TABLE `binlog_analyze` (
  `RECORD_TIME` varchar(30) COLLATE utf8_bin DEFAULT NULL,
  `DB_name` varchar(40) CHARACTER SET utf8 DEFAULT NULL,
  `TB_name` varchar(100) CHARACTER SET utf8 DEFAULT NULL,
  `OPERATION` varchar(10) CHARACTER SET utf8 DEFAULT NULL,
  `COUNT` bigint(20) DEFAULT NULL,
  `START_TIME` varchar(30) COLLATE utf8_bin DEFAULT NULL,
  `END_TIME` varchar(30) COLLATE utf8_bin DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin







#!/usr/local/python27/bin/python
#-*- coding: utf-8 -*-
# Analyze mysql binlog .

import MySQLdb

bin_log_file = open('/data/smb_sharepath/sup_home/binlog.dump')
method = ['INSERT','UPDATE','DELETE']
id = 1
i = 1



##Connect to mysql server
try:
    conn = MySQLdb.connect(host='192.168.0.105',user='miner',passwd='Miner~!',db='logminer',port=4406)
    cur = conn.cursor()
except MySQLdb.Error,e:
    print "Mysql Error %d: %s" % (e.args[0], e.args[1])


while True:
        line = bin_log_file.readline().split(' ')
        if line[0] == '':
            break
        if len(line[0]) == 7 and line[0][1] == '1':
#            print line
            if i == 1:
                if line[1] == '':
                    begin_time = line[0][1:3]+'-'+line[0][3:5]+'-'+line[0][5:7]+'/'+line[2]
                else:
                    begin_time = line[0][1:3]+'-'+line[0][3:5]+'-'+line[0][5:7]+'/'+line[1]
                i += 1
            else:
                if line[1] == '':
                    end_time = line[0][1:3]+'-'+line[0][3:5]+'-'+line[0][5:7]+'/'+line[2]
                else:
                    end_time = line[0][1:3]+'-'+line[0][3:5]+'-'+line[0][5:7]+'/'+line[1]
#       print line,len(line)
        if len(line) > 2 and line[1] in method:
#               print line
                if line[1] == 'UPDATE':
                        db_table = line[2].split('.')
                        db_name = db_table[0][1:-1]
                        table_name = db_table[1][1:-2]
                        try:
                            cur.execute('insert into operation_count_tmp_table values (%s,"UP_DATE",%s,%s)', (id,db_name,table_name))
                        except MySQLdb.Error,e:
                            print "Mysql Error %d: %s" % (e.args[0], e.args[1])
                        if id % 1000 == 0:
                            conn.commit()
                        id += 1
                else:
                        db_table = line[3].split('.')
                        db_name = db_table[0][1:-1]
                        table_name = db_table[1][1:-2]
                        operation = line[1]
                        try:
                            cur.execute('insert into operation_count_tmp_table values (%s,%s,%s,%s)',(id,operation,db_name,table_name))
                        except MySQLdb.Error,e:
                                print "Mysql Error %d: %s" % (e.args[0], e.args[1])
                        if id % 1000 == 0:
                            conn.commit()
                        id += 1
conn.commit()
try:
    cur.execute('INSERT INTO binlog_analyze () SELECT now(),Database_name AS DB_name,Table_name AS TB_name,OPERATION,count(*) AS count,%s,%s FROM operation_count_tmp_table GROUP BY Database_name,Table_name,OPERATION HAVING count(*) > 500',(begin_time,end_time))
except MySQLdb.Error,e:
    print "Mysql Error %d: %s" % (e.args[0], e.args[1])
conn.commit()
cur.execute('delete from operation_count_tmp_table')
conn.commit()
cur.close()
conn.close()