彻底挖掘mysqlbinlog数据内容

平时工作需要查询mysqlbinlog里面哪个库,哪个表在什么时间更新了什么数据,而通过mysqlbinlog转义过来的文件里面数据太乱,很多注释,而且也没有表结构相关字段,都用@1,@2等类似的方式显示,就想到通过python开发一个这样的功能。

先说下脚本的原理:

  1. 先通过mysqlbinlog转义二进制日志binlog文件,保存为一份临时文件(执行完后删除)
  2. 脚本连接数据库,查出对应的表结构和字段,然后替换掉对应的@1,@2等字段
  3. 过滤掉大部分注释的语句
  4. 然后...就没有然后了
    __author__ = 'chunyang.wu'
    # -*- coding: utf-8 -*-
    #!/usr/bin/env python
    import MySQLdb
    import re
    import os
    import sys
    
    mysql_config = {
        'host':'192.168.1.197',\
        'user':'root',\
        'passwd':'123456',\
        'port':3306,\
        'db':'mydb'
    }
    
    class Deal_binlog:
        def __init_db(self):
            self.mysql_db = MySQLdb.connect(host=self.host,user=self.user,passwd=self.passwd,port=self.port,db=self.db)
            self.mysql_cur=self.mysql_db.cursor()
    
        def __init__(self):
            self.host = mysql_config['host']
            self.user = mysql_config['user']
            self.passwd = mysql_config['passwd']
            self.port = mysql_config['port']
            self.db = mysql_config['db']
            self.sql_file = sys.argv[2]
            self.input_binlog_file = sys.argv[1]
            self.tmp_binlog_file = 'tmp_binlog_file'
            self.field = []
            self.tb_name = ''
            self.where = []
            self.update = []
            self.delete = []
            self.patt = re.compile("/* .* */")
            self.__init_db()
    
        def _release_db(self):
            self.mysql_cur.close()
            self.mysql_db.close()
    
        def _write_data(self,data):
            print data
            data = str(data)+"\n"
            f = open(self.data_file,'a+')
            f.write(data)
            f.close()
    
        def _get_table_name(self,line):
            try:
                if line.find('Table_map:')!=-1:
                    l = line.index('Table_map')
    #                print  line[l::].split(' ')
                    self.tb_name = line[l::].split(' ')[1].replace('`','')
    #                return table
            except Exception,ex:
                print ex
    
        def _get_table_structure(self,tb):
            desc_sql = 'desc %s' %tb
    #        print desc_sql
            self.field = []
            self.mysql_cur.execute(desc_sql)
            res = self.mysql_cur.fetchall()
            for j in res:
                self.field.append(j[0])
    
        def _do(self):
            '''先把mysql二进制的binlog解析成可识别文件,在从里面提取需要的数据'''
            if os.path.exists(self.sql_file):
                os.remove(self.sql_file)
            os.popen('mysqlbinlog -v -v --base64-output=DECODE-ROWS %s>%s' %(self.input_binlog_file,self.tmp_binlog_file))
            with open(self.tmp_binlog_file,"r") as infile:
                for line in infile:
                    if line.rstrip('\n')=='BEGIN':
                        line = line.replace('BEGIN','')
                    elif line.find('Table_map:')!=-1:
                        self._get_table_name(line)
                        self._get_table_structure(self.tb_name)
                    elif line.find('###   @')!=-1:
    #                    print line.replace('###   @','')
                        i = line.replace('###   @','').split('=')[0]
    #                    print line,i
                        line = line.replace('###   @'+str(i),self.field[int(i)-1])
                        if(int(i)== len(self.field)):
                            line = self.patt.sub(' ',line)
                        else:
                            line = self.patt.sub(',',line)
                    elif line.find('###')!=-1:
                        line = line.replace('###','')
                    else:
                        line = ''
                    if line.rstrip('\n')!= '':
                        print line.rstrip('\n')
                        f = open(self.sql_file,'a+')
                        f.write(line)
                        f.close()
            os.remove(self.tmp_binlog_file)
    
    def usage():
        print "python deal_binlog.py mysql_binlog_file out_put_sql_file"
        print "  tag: "
        print "  1. change mysql_config dict"
        print "  2. need MySQLdb"
        print "  3. need your mysql server desc table privileges"
    
    def main():
        p = Deal_binlog()
        p._do()
        p._release_db()
    
    if __name__=="__main__":
        if len(sys.argv) ==3:
            main()
        else:
            usage()

    脚本的执行方式:python deal_binlog.py mysql_binlog_file out_put_sql_file
    操作系统需要安装MySQLdb模块,且需要有权限连接到对应的数据库,脚本的执行可以不在mysql服务器上面(copy一份binlog文件即可)
    执行时需要把该脚本和复制的binlog放在同一个目录下,下面贴上一份解析后的结果图:
    可以看到哪个时间点,数据库更新了什么数据,我的目的这就达到了(update、delete语句不是标准sql语法,这里如果以后有需要在改了

---------------------------------------------------------------------------------------------------------------------------------------------------------

版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!
QQ:       380968195
Email:    380968195@qq.com
Blog:     http://blog.csdn.net/selectdb

URL:      http://blog.csdn.net/selectdb/article/details/16861063


对于使用mysqlbinlog恢复数据,您可以按照以下步骤进行操作: 1. 首先,您需要确保已经备份了要恢复的MySQL二进制日志文件(通常以binlog开头)。如果没有备份,恢复数据将会变得困难,甚至不可能。 2. 定位最新的完整备份文件和二进制日志文件。如果您只有备份文件而没有二进制日志文件,您可以使用该备份文件还原数据库,并且会丢失备份后的更改。 3. 在MySQL服务器上停止所有相关的服务,以确保数据一致性。可以使用以下命令: ``` sudo service mysql stop ``` 4. 使用mysqlbinlog命令来解析和恢复二进制日志文件。例如,使用以下命令从二进制日志文件中创建SQL语句文件: ``` mysqlbinlog <binlog文件名> > restore.sql ``` 5. 打开恢复.sql文件,并检查其中的SQL语句,确保其包含正确的恢复操作。可以使用文本编辑器进行编辑。 6. 重新启动MySQL服务并登录到MySQL服务器: ``` sudo service mysql start mysql -u <用户名> -p ``` 7. 在MySQL命令行中执行恢复.sql文件中的SQL语句: ``` source /path/to/restore.sql; ``` 8. 等待恢复操作完成。这可能需要一些时间,具体取决于二进制日志文件的大小和恢复操作的复杂性。 请注意,使用mysqlbinlog恢复数据可能会有一定的风险,因此在执行之前务必进行备份,并在恢复之前仔细检查和验证恢复的SQL语句。此外,根据具体情况可能需要额外的步骤和配置,请参考MySQL官方文档或专业人士的建议。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值