開發人員誤操作執行了update批量修改了資料庫中某個表某個欄位的值,現在想通過binlog去恢復執行update那個表之前的資料
因為不是整庫恢復,所以 先通過mysqlbinlog對binlog檔案進行轉化,轉化出來的sql為整庫的操作陳述句,然后再對需要恢復的表的操作陳述句進行提取,就是在提取的時候 遇到問題,不知道怎么提取,有高人指教一下嗎?
我的操作步驟如下:
1.將二進制日志轉化成sql檔案,修改資料的時間確定大致在11:55之前,所以上面匯出11:55之前的資料操作;
/usr/local/mysql/bin/mysqlbinlog -d test1 --base64-output=decode-rows -v --stop-datetime='2017-02-23 11:55:00' mysql_bin.000001 > test1.sql
貼出關鍵部分sql內容:
# at 319
#170217 10:28:23 server id 1 end_log_pos 392 CRC32 0x48479b8f Query thread_id=4 exec_time=0 error_code=0
SET TIMESTAMP=1487298503/*!*/;
BEGIN
/*!*/;
# at 392
#170217 10:28:23 server id 1 end_log_pos 445 CRC32 0xdb09ce03 Table_map: `test1`.`account` mapped to number 70
# at 445
#170217 10:28:23 server id 1 end_log_pos 547 CRC32 0xf2e41ab9 Update_rows: table id 70 flags: STMT_END_F
### UPDATE `test1`.`account`
### WHERE
### @1='zhangsan'
### SET
### @1='ceshi'
### UPDATE `test1`.`account`
### WHERE
### @1='lisi'
### SET
### @1='ceshi'
### UPDATE `test1`.`account`
### WHERE
### @1='wanger'
### SET
### @1='ceshi'
### UPDATE `test1`.`account`
### WHERE
### @1='mazi'
### SET
### @1='ceshi'
# at 547
#170217 10:28:23 server id 1 end_log_pos 578 CRC32 0x5ee48b32 Xid = 22
COMMIT/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
2.篩選出誤操作表的的陳述句:(網上看別人是這么操作的 可以篩選出來,我這樣篩選卻不對 不知道為什么)
more test1.sql |grep --ignore-case -E 'update' -A2 -B2|grep account
我篩選出的結果是:
[root@redis-slave data]# more test1.sql |grep --ignore-case -E 'update' -A2 -B2|grep account
#170217 10:28:23 server id 1 end_log_pos 445 CRC32 0xdb09ce03 Table_map: `test1`.`account` mapped to number 70
### UPDATE `test1`.`account`
### UPDATE `test1`.`account`
### UPDATE `test1`.`account`
### UPDATE `test1`.`account`
這結果明顯是不對的 有人告知一下為什么嗎?
如果篩選出來誤操作表的陳述句的話,就可以
more test1.sql |grep --ignore-case -E 'update' -A2 -B2|grep account > update.sql
然后執行update.sql就可以對誤操作表進行恢復了
uj5u.com熱心網友回復:
[root@c65muban data]# cat 1### UPDATE `test1`.`account`
### WHERE
### @1='zhangsan'
### SET
### @1='ceshi'
[root@c65muban data]# sed 's/###//g;s/SET/limit 1;/g;s/@1='"'"ceshi"'"'//g;s/WHERE/SET/g;s/@1/name/g' 1
UPDATE `test1`.`account`
SET
name='zhangsan'
limit 1;
[root@c65muban data]#
uj5u.com熱心網友回復:
網上那些grep a b 的做法都是錯的。你無法保證完整的sql陳述句位于匹配行的前后幾行。我以前寫過一個php腳本,可以試下,也有一些情況沒處理,比如依賴資料庫自增的set insertid。<?php
$sql_file="out.sql"; //完整的sql檔案
$tab_name="mod_son"; //要提取的表
$sql = new SplFileObject($sql_file);
$log=false;
foreach($sql as $line){ //逐行讀取
if ( preg_match("/^(SET TIMESTAMP=)/", $line) ) { //當前行找到匹配
$timestamp=$line;
}
if ( preg_match("/(create|delete|replace|insert|alter|update)([A-Z_\-\.\s\`]+){$tab_name}/i", $line) ) { //當前行找到匹配
file_put_contents($tab_name."_out.sql", $timestamp, FILE_APPEND); //時間戳
$log=true;
}
if ($log) {
file_put_contents($tab_name."_out.sql", $line, FILE_APPEND);
}
if ( $log && preg_match("/\/\*\!\*\/;/",$line) ){
$log=false;
}
}
echo "匯出完畢!\n";
uj5u.com熱心網友回復:
要根據情況寫,沒那么簡單,比如更數,列名的替換之類的uj5u.com熱心網友回復:
binlog2sql https://github.com/danfengcao/binlog2sqluj5u.com熱心網友回復:
https://github.com/danfengcao/binlog2sql 里面的篩選指定表日志好像沒用,uj5u.com熱心網友回復:
--base64-output=decode-rows 匯出不能用這個吧,直接用原來二進制的格式轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/28383.html
標籤:MySQL
上一篇:資料倉庫維度建模方法學習
下一篇:編譯pqlibxx.lib出錯
