【Mysql】从binlog中找出单个表的binlog信息
无聊研究binlog写了个提取单个表的binlog 的信息,便于误删恢复数据,这样做的目的是为了减少恢复时其他表可能引起的出错,以及缩短恢复时间
首先研究binlog日志的格式
思路就是先将第一部分以及最后一部分提取出来,我们csplite文件(以COMMIT/*!*/; 为分隔标示,不熟悉csplit命令的先去熟悉一下用法),在第一以及最后一部分中间插入单个表的binlog 信息而拼接成一个符合binlog格式的日志文件
测试:
TIP:脚本有点小bug,就是有时vcommit0 第一个begin commit可能记录的是别的表的信息而导致恢复时报错,那么就手工替换这部分的为第一个我们目标表的binlog信息再执行
标题名称:【Mysql】从binlog中找出单个表的binlog信息
本文来源:http://pwwzsj.com/article/ggoscc.html
首先研究binlog日志的格式
- 如下:
-
/*!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*/;
- 代码如下:
-
[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 ) ---循环从每个分割部分去找出单个表的信息
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: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 | -
-
- 模拟此时做了个备份
-
mysqldump -uroot -p`cat /etc/sqlpass ` -F TENNIS>TENNIS.sql --此时binlog到了19
- 模拟做些操作
-
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)
-
mysql> insert into TEAMS values(10,77,'oooo');
Query OK, 1 row affected (0.01 sec)
Query OK, 2 rows affected (0.01 sec)
Rows matched: 2 Changed: 2 Warnings: 0
-
恢复:
mysql> flush logs;
Query OK, 0 rows affected (0.00 sec)
[root@localhost chenliang]# mysql -uroot -p`cat /etc/sqlpass ` TENNIS
[root@localhost chenliang]# sh v1.sh --binlog=mysqlbin.000019 --database=TENNIS --table=TEAMS ---提前单表的binlog 信息
恢复binlog信息
[root@localhost chenliang]# mysql -uroot -p`cat /etc/sqlpass ` TENNIS
检查
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 |
+--------+----------+----------+
成功
mysql> flush logs;
Query OK, 0 rows affected (0.00 sec)
[root@localhost chenliang]# mysql -uroot -p`cat /etc/sqlpass ` TENNIS
[root@localhost chenliang]# sh v1.sh --binlog=mysqlbin.000019 --database=TENNIS --table=TEAMS ---提前单表的binlog 信息
点击(此处)折叠或打开
目前创新互联公司已为成百上千家的企业提供了网站建设、域名、虚拟空间、网站运营、企业网站设计、黄骅网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
- 查看提取出来的信息,删除update那部分即可
-
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信息删除即可
[root@localhost chenliang]# mysql -uroot -p`cat /etc/sqlpass ` TENNIS
检查
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可能记录的是别的表的信息而导致恢复时报错,那么就手工替换这部分的为第一个我们目标表的binlog信息再执行
标题名称:【Mysql】从binlog中找出单个表的binlog信息
本文来源:http://pwwzsj.com/article/ggoscc.html