溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

【Mysql】從binlog中找出單個表的binlog信息

發(fā)布時間:2020-08-07 02:27:08 來源:ITPUB博客 閱讀:405 作者:小亮520cl 欄目:MySQL數(shù)據(jù)庫
無聊研究binlog寫了個提取單個表的binlog 的信息,便于誤刪恢復(fù)數(shù)據(jù),這樣做的目的是為了減少恢復(fù)時其他表可能引起的出錯,以及縮短恢復(fù)時間
首先研究binlog日志的格式
  1. 如下:
  2. /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
    /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
    DELIMITER /*!*/;
    # at 4
    #160229 15:19:52 server id 162  end_log_pos 123 CRC32 0xbbe9b551 Start: binlog v 4, server v 5.7.9-log created 160229 15:19:52 at startup
    # Warning: this binlog is either in use or was not closed properly.
    ROLLBACK/*!*/;
    BINLOG '
    GPHTVg+iAAAAdwAAAHsAAAABAAQANS43LjktbG9nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAY8dNWEzgNAAgAEgAEBAQEEgAAXwAEGggAAAAICAgCAAAACgoKKioAEjQA
    AVG16bs=
    '/*!*/;
    # at 123
    #160229 15:19:52 server id 162  end_log_pos 154 CRC32 0xd473f6f4 Previous-GTIDs
    # [empty]
    # at 154
    #160229 15:18:07 server id 162  end_log_pos 219 CRC32 0xe86bb499 Anonymous_GTID last_committed=0 sequence_number=1
    SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
    # at 219
    #160229 15:18:07 server id 162  end_log_pos 291 CRC32 0xe1803afe Query thread_id=102887 exec_time=341 error_code=0
    SET TIMESTAMP=1456730287/*!*/;
    SET @@session.pseudo_thread_id=102887/*!*/;
    SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
    SET @@session.sql_mode=524288/*!*/;
    SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
    /*!\C latin1 *//*!*/;
    SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=33/*!*/;
    SET @@session.lc_time_names=0/*!*/;
    SET @@session.collation_database=DEFAULT/*!*/;
    BEGIN
    /*!*/;
    # at 291
    #160229 15:18:07 server id 162  end_log_pos 343 CRC32 0xcfc435f2 Table_map: `test`.`ty` mapped to number 127
    # at 343
    #160229 15:18:07 server id 162  end_log_pos 463 CRC32 0xb4ef18fe Write_rows: table id 127 flags: STMT_END_F
    BINLOG '
    r/DTVhOiAAAANAAAAFcBAAAAAH8AAAAAAAEABHRlc3QAAnR5AAQDDw8DBBQAFAAP8jXEzw==
    r/DTVh7iAAAAeAAAAM8BAAAAAH8AAAAAAAEAAgAE//AFAAAABEVFRUUCQzFfAAAA8AEAAAAEQUFB
    QQJDMUMAAADwAwAAAARDQ0NDAkMxQwAAAPAEAAAABEREREQCQzFBAAAA8AIAAAAEQkJCQgJDMTcA
    AAD+GO+0
    '/*!*/;
    # at 463
    #160229 15:18:07 server id 162  end_log_pos 494 CRC32 0xed1fb95b Xid = 53


    COMMIT/*!*/;                                                                                                              -------到第一個commit為第一部分 為binlog必須的,缺失會報錯
    # at 494
    #160229 15:18:07 server id 162  end_log_pos 559 CRC32 0xef3ac14c Anonymous_GTID last_committed=1 sequence_number=2
    SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
    # at 559
    #160229 15:18:07 server id 162  end_log_pos 631 CRC32 0xe834f1d8 Query thread_id=102887 exec_time=350 error_code=0
    SET TIMESTAMP=1456730287/*!*/;
    BEGIN
    /*!*/;
    # at 631
    #160229 15:18:07 server id 162  end_log_pos 683 CRC32 0xc64ac724 Table_map: `test`.`ty` mapped to number 127
    # at 683
    #160229 15:18:07 server id 162  end_log_pos 803 CRC32 0x4a5f1c75 Write_rows: table id 127 flags: STMT_END_F
    BINLOG '
    r/DTVhOiAAAANAAAAKsCAAAAAH8AAAAAAAEABHRlc3QAAnR5AAQDDw8DBBQAFAAPJMdKxg==
    r/DTVh7iAAAAeAAAACMDAAAAAH8AAAAAAAEAAgAE//AFAAAABEVFRUUCQzFfAAAA8AEAAAAEQUFB
    QQJDMUMAAADwAwAAAARDQ0NDAkMxQwAAAPAEAAAABEREREQCQzFBAAAA8AIAAAAEQkJCQgJDMTcA
    AAB1HF9K
    '/*!*/;
    # at 803
    #160229 15:18:07 server id 162  end_log_pos 834 CRC32 0x96148022 Xid = 77



    COMMIT/*!*/;                                                                                                              ------到下一個commit為第二部分,一個事物語句,可以缺失
    # at 834
    #160229 15:18:07 server id 162  end_log_pos 899 CRC32 0xa1e52982 Anonymous_GTID last_committed=2 sequence_number=3
    SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
    # at 899
    #160229 15:18:07 server id 162  end_log_pos 971 CRC32 0x89fc0e48 Query thread_id=102887 exec_time=359 error_code=0
    SET TIMESTAMP=1456730287/*!*/;
    BEGIN
    /*!*/;
    # at 971
    #160229 15:18:07 server id 162  end_log_pos 1023 CRC32 0xc1309696 Table_map: `test`.`ty` mapped to number 127
    # at 1023
    #160229 15:18:07 server id 162  end_log_pos 1143 CRC32 0x0993d08b Write_rows: table id 127 flags: STMT_END_F
    BINLOG '
    r/DTVhOiAAAANAAAAP8DAAAAAH8AAAAAAAEABHRlc3QAAnR5AAQDDw8DBBQAFAAPlpYwwQ==
    r/DTVh7iAAAAeAAAAHcEAAAAAH8AAAAAAAEAAgAE//AFAAAABEVFRUUCQzFfAAAA8AEAAAAEQUFB
    QQJDMUMAAADwAwAAAARDQ0NDAkMxQwAAAPAEAAAABEREREQCQzFBAAAA8AIAAAAEQkJCQgJDMTcA
    AACL0JMJ
    '/*!*/;
    # at 1143
    #160229 15:18:07 server id 162  end_log_pos 1174 CRC32 0x7c2054fd Xid = 101



                                                                                                                               。。。。。省略                                               




    COMMIT/*!*/;                                                                                                                -------最后一個commit到最后必須存在
    SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
    DELIMITER ;
    # End of log file
    /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
    /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
思路就是先將第一部分以及最后一部分提取出來,我們csplite文件(以COMMIT/*!*/; 為分隔標示,不熟悉csplit命令的先去熟悉一下用法),在第一以及最后一部分中間插入單個表的binlog 信息而拼接成一個符合binlog格式的日志文件


  1. 代碼如下:
  2. [root@localhost chenliang]# more v1.sh 
    #!/bin/bash
    # author:Jonnychen
    # date:2016-3-1
    # set -x


    # get the key value of input
    get_key_value()
    {
            echo "$1" | sed 's/^--[A-Za-z_-]*=//'
    }




    use_help()
    {
    cat << EOF
            Info :
                    Author:Michael.xu
            Usage :
            Usage : $0 [configure-options]
                    -? , --help
                    --binlog=<> , set binlogfile
                    --database=<> , set database
                    --table=<>,set table
    EOF
    }




    parse_options()
    {
            while [ $# -gt 0 ]
            do
                    case "$1" in
                            --binlog=*)
                                    vbinlog=`get_key_value "$1"`;;
                            --database=*)
                                    vdatabase=`get_key_value "$1"`;;
                            --table=*)
                                    vtable=`get_key_value "$1"`;;
                            -? | --help)
                                    use_help
                                    exit 0;;
                            *)
                                    echo "unknown configure option '$1'"
                                    exit 1;;
                    esac
                    shift
            done
    }








    parse_options "$@"
    echo "$vbinlog,$vdatabase,$vtable"




    if [ ! -n "$vbinlog" ];then    
         use_help
         exit
    fi




    if [ ! -n "$vdatabase" ];then
         use_help
         exit
    fi


    if [ ! -n "$vtable" ];then
         use_help
         exit
    fi


    #####binlog日志格式化為txt文件
    mysqlbinlog_dir=`which mysqlbinlog`
    ${mysqlbinlog_dir} ${vbinlog}>${vbinlog}.txt
    filename=${vbinlog}.txt


    #####txt日志文件按照commit字段進行切割
    csplit $filename /COMMIT\/*\// -n 1 -s {*} -f vcommit


    cou_comm=`ls -l | grep vcommit|awk -F " " '{print $9}'|wc -l`
    let "maxseq=${cou_comm}-1"
    #echo $maxseq
    let "sec_max=$maxseq-1"
    #echo ${sec_max}




    cat vcommit0>>${vbinlog}.sql                     #####提取第一部分


    for((i=1;i<=${sec_max};i++))
    do
       hastab=$(grep "\`${vdatabase}\`.\`${vtable}\`" vcommit$i|wc -l )     ---循環(huán)從每個分割部分去找出單個表的信息
       echo "vcommit$i:$hastab"
       if [ $hastab -ge 1 ]
          then
            cat vcommit$i>>${vbinlog}.sql
       fi
    done


    cat vcommit$maxseq>>${vbinlog}.sql             ###提取最后一部分
     


    rm -rf $filename vcommit*                     




測試:

  1. 1:mysql> select * from TEAMS;   原始數(shù)據(jù)
  2. +--------+----------+----------+
    | TEAMNO | PLAYERNO | DIVISION |
    +--------+----------+----------+
    |      1 |        6 | first    |
    |      2 |       27 | second   |
    |      3 |       89 | asd      |
    |      4 |       89 | BBBB     |
    |      5 |       89 | DDDD     |
    |      6 |       67 | GGGG     |
    |      7 |       77 | KKKK     |


  3. 模擬此時做了個備份
  4. mysqldump -uroot -p`cat /etc/sqlpass ` -F TENNIS>TENNIS.sql   --此時binlog到了19
  1. 模擬做些操作
  2. mysql> insert into TEAMS values(8,77,'uuuuuu');
    Query OK, 1 row affected (0.00 sec)


    mysql> insert into TEAMS values(9,77,'iiiiii');
    Query OK, 1 row affected (0.00 sec)
  3. mysql> insert into TEAMS values(10,77,'oooo');
    Query OK, 1 row affected (0.01 sec)

    mysql> update TEAMS set DIVISION='pppp' where TEAMNO in(9,10);   ---誤操作
    Query OK, 2 rows affected (0.01 sec)
    Rows matched: 2  Changed: 2  Warnings: 0


恢復(fù):
mysql> flush logs;
Query OK, 0 rows affected (0.00 sec)

[root@localhost chenliang]# mysql -uroot -p`cat /etc/sqlpass ` TENNIS<TENNIS.sql  --恢復(fù)備份

[root@localhost chenliang]# sh v1.sh --binlog=mysqlbin.000019 --database=TENNIS --table=TEAMS   ---提前單表的binlog 信息

點擊(此處)折疊或打開

  1. 查看提取出來的信息,刪除update那部分即可
  2. COMMIT/*!*/;
    # at 704
    #160301 13:55:35 server id 162  end_log_pos 769 CRC32 0x0593de75        Anonymous_GTID  last_committed=2        sequence_number=3
    SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
    # at 769
    #160301 13:55:35 server id 162  end_log_pos 843 CRC32 0x2978f290        Query   thread_id=2     exec_time=0     error_code=0
    SET TIMESTAMP=1456811735/*!*/;
    BEGIN
    /*!*/;
    # at 843
    #160301 13:55:35 server id 162  end_log_pos 897 CRC32 0xe52bc252        Table_map: `TENNIS`.`TEAMS` mapped to number 134
    # at 897
    #160301 13:55:35 server id 162  end_log_pos 946 CRC32 0x7331e254        Update_rows: table id 134 flags: STMT_END_F


    BINLOG '
    1y7VVhOiAAAANgAAAIEDAAAAAIYAAAAAAAEABlRFTk5JUwAFVEVBTVMAAwMD/gL+EgBSwivl
    1y7VVh7iAAAAMQAAALIDAAAAAIYAAAAAAAEAAgAD//gKAAAATQAAAARvb29vVOIxcw==
    '/*!*/;
    # at 946
    #160301 13:55:35 server id 162  end_log_pos 977 CRC32 0x7da650c4        Xid = 271
    COMMIT/*!*/;   ----從sql中將update的binlog信息刪除即可
恢復(fù)binlog信息
[root@localhost chenliang]# mysql -uroot -p`cat /etc/sqlpass ` TENNIS<mysqlbin.000019.sql

檢查
mysql> select * from TEAMS;
+--------+----------+----------+
| TEAMNO | PLAYERNO | DIVISION |
+--------+----------+----------+
|      1 |        6 | first    |
|      2 |       27 | second   |
|      3 |       89 | asd      |
|      4 |       89 | BBBB     |
|      5 |       89 | DDDD     |
|      6 |       67 | GGGG     |
|      7 |       77 | KKKK     |
|      8 |       77 | uuuuuu   |
|      9 |       77 | iiiiii   |
|     10 |       77 | oooo     |
+--------+----------+----------+
成功

TIP:腳本有點小bug,就是有時vcommit0 第一個begin commit可能記錄的是別的表的信息而導(dǎo)致恢復(fù)時報錯,那么就手工替換這部分的為第一個我們目標表的binlog信息再執(zhí)行

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI