Chinaunix首页 | 论坛 | 博客
  • 博客访问: 109971
  • 博文数量: 13
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 195
  • 用 户 组: 普通用户
  • 注册时间: 2012-10-23 13:16
个人简介

数据库领域专心吃草

文章分类

全部博文(13)

文章存档

2015年(1)

2014年(4)

2013年(8)

我的朋友

分类: Mysql/postgreSQL

2015-06-10 20:59:45

在维护mysql的经验中,很多时候我们需要进行单表恢复,以应对误操作 或者sql注入引起的故障,本人也在实际的工作中遇到若干次开发误操作需要恢复数据的情况。
为了方便的恢复数据,所以写了一个逆向解析binlog的工具,能够方便的进行单表恢复操作。目前仅支持5.5,binlog格式必须为row格式
工具下载地址:,具体的限制以及使用方法请查看README

使用演示:
创建表unit.t1

点击(此处)折叠或打开

  1. create table t1(c1 int not null primary key,c2 varchar(50),c3 datetime)
插入部分数据:

点击(此处)折叠或打开

  1. unit> insert into t1 values (1,"xxxx",now());
  2. Query OK, 1 row affected (0.00 sec)

  3. unit> insert into t1 values (2,"a",now());
  4. Query OK, 1 row affected (0.00 sec)

  5. unit> insert into t1 values (3,"b",now());
  6. Query OK, 1 row affected (0.00 sec)

  7. unit> select * from t1;
  8. +----+------+---------------------+
  9. | c1 | c2 | c3 |
  10. +----+------+---------------------+
  11. | 1 | xxxx | 2015-06-10 20:33:34 |
  12. | 2 | a | 2015-06-10 20:33:40 |
  13. | 3 | b | 2015-06-10 20:33:46 |
  14. +----+------+---------------------+
  15. 3 rows in set (0.00 sec)
这时候我们模拟一个误操作,删除所有的数据:

点击(此处)折叠或打开

  1. unit> delete from t1;
  2. Query OK, 3 rows affected (0.00 sec)
查看binlog:

点击(此处)折叠或打开

  1. # at 4573
  2. #150610 20:33:34 server id 5295721 end_log_pos 4649 Query thread_id=909740 exec_time=0 error_code=0
  3. SET TIMESTAMP=1433939614/*!*/;
  4. SET @@session.time_zone='SYSTEM'/*!*/;
  5. BEGIN
  6. /*!*/;
  7. # at 4649
  8. # at 4694
  9. #150610 20:33:34 server id 5295721 end_log_pos 4694 Table_map: `unit`.`t1` mapped to number 83
  10. #150610 20:33:34 server id 5295721 end_log_pos 4741 Write_rows: table id 83 flags: STMT_END_F

  11. BINLOG '
  12. ni54VRNpzlAALQAAAFYSAAAAAFMAAAAAAAEABHVuaXQAAnQxAAMDDwwClgAG
  13. ni54VRdpzlAALwAAAIUSAAAAAFMAAAAAAAEAA//4AQAAAAR4eHh4xpL2rVMSAAA=
  14. '/*!*/;
  15. ### INSERT INTO unit.t1
  16. ### SET
  17. ### @1=1 /* INT meta=0 nullable=0 is_null=0 */
  18. ### @2='xxxx' /* VARSTRING(150) meta=150 nullable=1 is_null=0 */
  19. ### @3=2015-06-10 20:33:34 /* DATETIME meta=0 nullable=1 is_null=0 */
  20. # at 4741
  21. #150610 20:33:34 server id 5295721 end_log_pos 4768 Xid = 3484054
  22. COMMIT/*!*/;
  23. # at 4768
  24. #150610 20:33:40 server id 5295721 end_log_pos 4844 Query thread_id=909740 exec_time=0 error_code=0
  25. SET TIMESTAMP=1433939620/*!*/;
  26. BEGIN
  27. /*!*/;
  28. # at 4844
  29. # at 4889
  30. #150610 20:33:40 server id 5295721 end_log_pos 4889 Table_map: `unit`.`t1` mapped to number 83
  31. #150610 20:33:40 server id 5295721 end_log_pos 4933 Write_rows: table id 83 flags: STMT_END_F

  32. BINLOG '
  33. pC54VRNpzlAALQAAABkTAAAAAFMAAAAAAAEABHVuaXQAAnQxAAMDDwwClgAG
  34. pC54VRdpzlAALAAAAEUTAAAAAFMAAAAAAAEAA//4AgAAAAFhzJL2rVMSAAA=
  35. '/*!*/;
  36. ### INSERT INTO unit.t1
  37. ### SET
  38. ### @1=2 /* INT meta=0 nullable=0 is_null=0 */
  39. ### @2='a' /* VARSTRING(150) meta=150 nullable=1 is_null=0 */
  40. ### @3=2015-06-10 20:33:40 /* DATETIME meta=0 nullable=1 is_null=0 */
  41. # at 4933
  42. #150610 20:33:40 server id 5295721 end_log_pos 4960 Xid = 3484055
  43. COMMIT/*!*/;
  44. # at 4960
  45. #150610 20:33:46 server id 5295721 end_log_pos 5036 Query thread_id=909740 exec_time=0 error_code=0
  46. SET TIMESTAMP=1433939626/*!*/;
  47. BEGIN
  48. /*!*/;
  49. # at 5036
  50. # at 5081
  51. #150610 20:33:46 server id 5295721 end_log_pos 5081 Table_map: `unit`.`t1` mapped to number 83
  52. #150610 20:33:46 server id 5295721 end_log_pos 5125 Write_rows: table id 83 flags: STMT_END_F

  53. BINLOG '
  54. qi54VRNpzlAALQAAANkTAAAAAFMAAAAAAAEABHVuaXQAAnQxAAMDDwwClgAG
  55. qi54VRdpzlAALAAAAAUUAAAAAFMAAAAAAAEAA//4AwAAAAFi0pL2rVMSAAA=
  56. '/*!*/;
  57. ### INSERT INTO unit.t1
  58. ### SET
  59. ### @1=3 /* INT meta=0 nullable=0 is_null=0 */
  60. ### @2='b' /* VARSTRING(150) meta=150 nullable=1 is_null=0 */
  61. ### @3=2015-06-10 20:33:46 /* DATETIME meta=0 nullable=1 is_null=0 */
  62. # at 5125
  63. #150610 20:33:46 server id 5295721 end_log_pos 5152 Xid = 3484056
  64. COMMIT/*!*/;
  65. # at 5152
  66. #150610 20:35:52 server id 5295721 end_log_pos 5220 Query thread_id=909740 exec_time=0 error_code=0
  67. SET TIMESTAMP=1433939752/*!*/;
  68. BEGIN
  69. /*!*/;
  70. # at 5220
  71. # at 5265
  72. #150610 20:35:52 server id 5295721 end_log_pos 5265 Table_map: `unit`.`t1` mapped to number 83
  73. #150610 20:35:52 server id 5295721 end_log_pos 5342 Delete_rows: table id 83 flags: STMT_END_F

  74. BINLOG '
  75. KC94VRNpzlAALQAAAJEUAAAAAFMAAAAAAAEABHVuaXQAAnQxAAMDDwwClgAG
  76. KC94VRlpzlAATQAAAN4UAAAAAFMAAAAAAAEAA//4AQAAAAR4eHh4xpL2rVMSAAD4AgAAAAFhzJL2
  77. rVMSAAD4AwAAAAFi0pL2rVMSAAA=
  78. '/*!*/;
  79. ### DELETE FROM unit.t1
  80. ### WHERE
  81. ### @1=1 /* INT meta=0 nullable=0 is_null=0 */
  82. ### @2='xxxx' /* VARSTRING(150) meta=150 nullable=1 is_null=0 */
  83. ### @3=2015-06-10 20:33:34 /* DATETIME meta=0 nullable=1 is_null=0 */
  84. ### DELETE FROM unit.t1
  85. ### WHERE
  86. ### @1=2 /* INT meta=0 nullable=0 is_null=0 */
  87. ### @2='a' /* VARSTRING(150) meta=150 nullable=1 is_null=0 */
  88. ### @3=2015-06-10 20:33:40 /* DATETIME meta=0 nullable=1 is_null=0 */
  89. ### DELETE FROM unit.t1
  90. ### WHERE
  91. ### @1=3 /* INT meta=0 nullable=0 is_null=0 */
  92. ### @2='b' /* VARSTRING(150) meta=150 nullable=1 is_null=0 */
  93. ### @3=2015-06-10 20:33:46 /* DATETIME meta=0 nullable=1 is_null=0 */
  94. # at 5342
  95. #150610 20:35:52 server id 5295721 end_log_pos 5369 Xid = 3484242
  96. COMMIT/*!*/;
  97. DELIMITER ;
  98. # End of log file
  99. ROLLBACK /* added by mysqlbinlog */;
  100. /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/
可以看到我们的insert操作和delete操作,在时间2015-06-10 20:35:52 我们做了delete误操作。现在我们要恢复到这个时间点

点击(此处)折叠或打开

  1. [root@centos mysql_6302_binlog]# python binlogback.py -f ./mysql-bin.000022 -B unit -m desc -t t1 -c "c1,c2,c3" --begin-datetime="2015-06-10 20:35:52"
  2. #pos:5342
  3. BEGIN;
  4. insert into `unit`.`t1`(`c1`,`c2`,`c3`)values ( 3, 'b', '2015-06-10 20:33:46');
  5. insert into `unit`.`t1`(`c1`,`c2`,`c3`)values ( 2, 'a', '2015-06-10 20:33:40');
  6. insert into `unit`.`t1`(`c1`,`c2`,`c3`)values ( 1, 'xxxx', '2015-06-10 20:33:34');
  7. COMMIT
可以看到工具把delete语句按照反序转换成了insert语句,把生成的语句执行:

点击(此处)折叠或打开

  1. unit> BEGIN;
  2. Query OK, 0 rows affected (0.00 sec)

  3. unit> insert into `unit`.`t1`(`c1`,`c2`,`c3`)values ( 3, 'b', '2015-06-10 20:33:46');
  4. Query OK, 1 row affected (0.00 sec)

  5. unit> insert into `unit`.`t1`(`c1`,`c2`,`c3`)values ( 2, 'a', '2015-06-10 20:33:40');
  6. Query OK, 1 row affected (0.00 sec)

  7. unit> insert into `unit`.`t1`(`c1`,`c2`,`c3`)values ( 1, 'xxxx', '2015-06-10 20:33:34');
  8. Query OK, 1 row affected (0.00 sec)

  9. unit> COMMIT;
  10. Query OK, 0 rows affected (0.00 sec)

  11. unit> select * from t1;
  12. +----+------+---------------------+
  13. | c1 | c2 | c3 |
  14. +----+------+---------------------+
  15. | 1 | xxxx | 2015-06-10 20:33:34 |
  16. | 2 | a | 2015-06-10 20:33:40 |
  17. | 3 | b | 2015-06-10 20:33:46 |
  18. +----+------+---------------------+
  19. 3 rows in set (0.00 sec)

可以看到表t1已经恢复到了我们删除前的状态。

工具限制:
1、要恢复的表必须有主键,不然恢复可能会引起严重的数据错误
2、目前仅支持mysql5.5,以及5.5的衍生版本,只要binlog协议没有发生改变,原理上都适用
3、只支持row格式的binlog
4、time类型解析有问题,如果time类型的值小于“00:00:00”那么会解析出错误的值
5、因为工作时间问题,暂时没有支持设置binlog position来恢复数据,后续会支持
优点:
1、方便快捷,单表恢复
2、修复了5.5的mysqlbinlog工具的一些BUG
3、使用python,没有依赖,下载即可使用

该工具是博主最近研究binlog协议生产出来的一个小工具,欢迎大家试用,多提BUG,多多交流。代码没有经过严格的构思,请勿吐槽代码水平









阅读(5142) | 评论(2) | 转发(0) |
3

上一篇:mysql导出用户权限

下一篇:没有了

给主人留下些什么吧!~~

visician2015-07-20 14:06:29

守候2581314:脚本能共享下吗

文中有github地址,不过脚本效率不高,比较慢,有待改善

回复 | 举报

守候25813142015-07-09 17:38:07

脚本能共享下吗