MySQL闪回实现
来自技术开发小组内部wiki
前提:binlog_format=row,因为只有row模式会记录更新前后的整行记录。
原理
1.单个语句的闪回
平时的DML无非三种操作,增删改,先说三种操作的日志格式。 一个语句分成两个event (实际上不止,其他可以忽略),一个table_map event 和 一个Rows_log_event。Table_map event是一样的,主要看Rows_log_event。 每个Rows_log_event中包含event_type, 可选值为WRITE_ROWS_EVENT、UPDATE_ROWS_EVENT、DELETE_ROWS_EVENT。从宏名字就能看出用途。 对于insert和delete,event中包含了插入/删除的记录的所有字段的值。 对于update操作,event中依次记录旧行, 新行的值。 因此我们看到,这些信息足够让我们对单个操作实现“逆操作”。 i.对于insert操作,只需要把event_type改成DELETE_ROWS_EVENT;对于delete操作,改成WRITE_ROWS_EVENT。 ii.对于update操作,只需要把event中的旧行和新行值对调即可。
2.binlog的闪回
我们只需要把binlog文件反向执行,每个操作都执行逆操作即可。当然也不是所有的event都反转。Table_map event必须还是在Rows_log_event每个操作之前。 目前的方案是用 mysqlbinlog工具,增加一个flashback参数,输出结果为一个新的binlog文件――姑且叫做flashbacklog,这个flashbacklog顺序执行, 可制定某张表和执行到 哪个pos,来实现数据库的闪回。
安装
tar xvfz mysql-5.5.18.tar.gz cd mysql-5.5.18 patch -p0 < /work/5.5.18_flashback.diff cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql_flashback make make install
生成的mysqlbinlog文件就带有闪回功能,为使用方便,复制一份到mysql的bin目录,并更名为mysqlflashback。 cp mysqlbinlog mysqlflashback
使用
-B参数,指定用于闪回数据。其它参数同mysqlbin。 mysqlflashback -B -vv --start-position=298 --stop-position=553 mysql-bin.000001 > /work/01.sql --查看 mysqlflashback -B -vv --start-position=298 --stop-position=553 mysql-bin.000001 | mysql -S/tmp/mysql55.sock test --执行闪回
position获取一例: update执行过程 Query--Table_map--Update_rows--COMMIT,如下回滚position为298-553 # at 298 #140430 11:19:04 server id 1 end_log_pos 366 Query thread_id=3 exec_time=0 error_code=0 . . # at 366 # at 412 #140430 11:19:04 server id 1 end_log_pos 412 Table_map: `test`.`tt` mapped to number 39 #140430 11:19:04 server id 1 end_log_pos 526 Update_rows: table id 39 flags: STMT_END_F . . # at 526 #140430 11:19:04 server id 1 end_log_pos 553 Xid = 682 COMMIT/*!*/;
参考
http://dinglin.iteye.com/blog/1539167 http://mysql.taobao.org/index.php/Patch_source_code#Add_flashback_feature_for_mysqlbinlog(工具的源码补丁包下载地址)