UPDATE或者DELETE忘加WHERE條件的恢復

一、創建測試表html

mysql> create table test( 
    -> id int not null auto_increment, 
    -> name char(20) not null, 
    -> sex char(4) not null, 
    -> score varchar(10) not null, 
    -> primary key(id) 
    -> ); 
Query OK, 0 rows affected (0.11 sec)

二、插入數據mysql

mysql> insert into test(name,sex,score) values('張三','男',86); 
Query OK, 1 row affected (0.01 sec) 
…… 
mysql> select * from test; 
+----+--------+-----+-------+ 
| id | name   | sex | score | 
+----+--------+-----+-------+ 
|  1 | 張三   | 男  | 86    | 
|  2 | 李四   | 男  | 88    | 
|  3 | 王五   | 男  | 90    | 
|  4 | 麻六   | 男  | 92    | 
|  5 | 小芳   | 女  | 94    | 
|  6 | 小紅   | 女  | 100   | 
+----+--------+-----+-------+ 
6 rows in set (0.00 sec)

mysql> update test set sex='tom'; 
Query OK, 6 rows affected (0.00 sec) 
Rows matched: 6  Changed: 6  Warnings: 0 
   
mysql> select * from test; 
+----+--------+-----+-------+ 
| id | name   | sex | score | 
+----+--------+-----+-------+ 
|  1 | 張三   | tom | 86    | 
|  2 | 李四   | tom | 88    | 
|  3 | 王五   | tom | 90    | 
|  4 | 麻六   | tom | 92    | 
|  5 | 小芳   | tom | 94    | 
|  6 | 小紅   | tom | 100   | 
+----+--------+-----+-------+ 
6 rows in set (0.00 sec)

三、開始恢復,生產環境鎖表,避免數據被再次污染sql

mysql> lock tables test read; 
Query OK, 0 rows affected (0.00 sec) 
mysql> insert into test(name,sex,score) values('小芳','女',94); 
ERROR 1099 (HY000): Table 'test' was locked with a READ lock and can't be updated 
mysql> show master status; 
+------------------+----------+--------------+------------------+ 
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | 
+------------------+----------+--------------+------------------+ 
| mysql-bin.000001 |     1816 |              |                  | 
+------------------+----------+--------------+------------------+ 
1 row in set (0.00 sec)

四、分析二進制日誌服務器

[root@xiaoya data]# mysqlbinlog --no-defaults -v -v --base64-output=DECODE-ROWS mysql-bin.000001 |grep -B 15 '中' 
BEGIN 
/*!*/; 
# at 1513 
# at 1569 
#160713 13:52:06 server id 1  end_log_pos 1569   Table_map: `students`.`test` mapped to number 33 
#160713 13:52:06 server id 1  end_log_pos 1789   Update_rows: table id 33 flags: STMT_END_F 
### UPDATE `students`.`test` 
### WHERE 
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='張三' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='男' /* STRING(12) meta=65036 nullable=0 is_null=0 */ 
###   @4='86' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */ 
### SET 
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='張三' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='中' /* STRING(12) meta=65036 nullable=0 is_null=0 */ 
###   @4='86' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */ 
### UPDATE `students`.`test` 
### WHERE 
###   @1=2 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='李四' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='男' /* STRING(12) meta=65036 nullable=0 is_null=0 */ 
###   @4='88' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */ 
### SET 
###   @1=2 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='李四' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='中' /* STRING(12) meta=65036 nullable=0 is_null=0 */ 
###   @4='88' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */ 
### UPDATE `students`.`test` 
### WHERE 
###   @1=3 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='王五' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='男' /* STRING(12) meta=65036 nullable=0 is_null=0 */ 
###   @4='90' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */ 
### SET 
###   @1=3 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='王五' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='中' /* STRING(12) meta=65036 nullable=0 is_null=0 */ 
###   @4='90' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */ 
### UPDATE `students`.`test` 
### WHERE 
###   @1=4 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='小紅' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='女' /* STRING(12) meta=65036 nullable=0 is_null=0 */ 
###   @4='92' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */ 
### SET 
###   @1=4 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='小紅' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='中' /* STRING(12) meta=65036 nullable=0 is_null=0 */ 
###   @4='92' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */ 
### UPDATE `students`.`test` 
### WHERE 
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='小芳' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='女' /* STRING(12) meta=65036 nullable=0 is_null=0 */ 
###   @4='96' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */ 
### SET 
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='小芳' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='中' /* STRING(12) meta=65036 nullable=0 is_null=0 */

Binlog記錄了每一行的變化狀況,這裏binlog格式必須是row,咱們要作的就是把binlog轉化成sql從新插入。微信

六、分析、處理二進制日誌app

[root@xiaoya data]# mysqlbinlog --no-defaults -v -v --base64-output=DECODE-ROWS mysql-bin.000001 |sed -n '/# at 1569/,/# at 1789/p' >mysql-test.txt 
[root@xiaoya data]# cat mysql-test.txt 
# at 1569 
#160713 13:52:06 server id 1  end_log_pos 1569   Table_map: `students`.`test` mapped to number 33 
#160713 13:52:06 server id 1  end_log_pos 1789   Update_rows: table id 33 flags: STMT_END_F 
### UPDATE `students`.`test` 
### WHERE 
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='張三' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='男' /* STRING(12) meta=65036 nullable=0 is_null=0 */ 
###   @4='86' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */ 
### SET 
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='張三' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='中' /* STRING(12) meta=65036 nullable=0 is_null=0 */ 
###   @4='86' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */ 
### UPDATE `students`.`test` 
### WHERE 
###   @1=2 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='李四' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='男' /* STRING(12) meta=65036 nullable=0 is_null=0 */ 
###   @4='88' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */ 
### SET 
###   @1=2 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='李四' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='中' /* STRING(12) meta=65036 nullable=0 is_null=0 */ 
###   @4='88' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */ 
### UPDATE `students`.`test` 
### WHERE 
###   @1=3 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='王五' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='男' /* STRING(12) meta=65036 nullable=0 is_null=0 */ 
###   @4='90' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */ 
### SET 
###   @1=3 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='王五' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='中' /* STRING(12) meta=65036 nullable=0 is_null=0 */ 
###   @4='90' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */ 
### UPDATE `students`.`test` 
### WHERE 
###   @1=4 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='小紅' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='女' /* STRING(12) meta=65036 nullable=0 is_null=0 */ 
###   @4='92' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */ 
### SET 
###   @1=4 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='小紅' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='中' /* STRING(12) meta=65036 nullable=0 is_null=0 */ 
###   @4='92' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */ 
### UPDATE `students`.`test` 
### WHERE 
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='小芳' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='女' /* STRING(12) meta=65036 nullable=0 is_null=0 */ 
###   @4='96' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */ 
### SET 
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */ 
###   @2='小芳' /* STRING(60) meta=65084 nullable=0 is_null=0 */ 
###   @3='中' /* STRING(12) meta=65036 nullable=0 is_null=0 */ 
###   @4='96' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */ 
# at 1789

下面有一個神奇的sed測試

[root@xiaoya data]# sed '/WHERE/{:a;N;/SET/!ba;s/\([^\n]*\)\n\(.*\)\n\(.*\)/\3\n\2\n\1/}' mysql-test.txt | sed -r '/WHERE/{:a;N;/@4/!ba;s/###   @2.*//g}' | sed 's/### //g;s/\/\*.*/,/g' | sed '/WHERE/{:a;N;/@1/!ba;s/,/;/g};s/#.*//g;s/COMMIT,//g' | sed '/^$/d' 
UPDATE `students`.`test` 
SET 
  @1=1 , 
  @2='張三' , 
  @3='男' , 
  @4='86' , 
WHERE 
  @1=1 ; 
UPDATE `students`.`test` 
SET 
  @1=2 , 
  @2='李四' , 
  @3='男' , 
  @4='88' , 
WHERE 
  @1=2 ; 
UPDATE `students`.`test` 
SET 
  @1=3 , 
  @2='王五' , 
  @3='男' , 
  @4='90' , 
WHERE 
  @1=3 ; 
UPDATE `students`.`test` 
SET 
  @1=4 , 
  @2='小紅' , 
  @3='女' , 
  @4='92' , 
WHERE 
  @1=4 ; 
UPDATE `students`.`test` 
SET 
  @1=5 , 
  @2='小芳' , 
  @3='女' , 
  @4='96' , 
WHERE 
  @1=5 ;

下面這個就相對簡單了日誌

[root@xiaoya data]# sed -i 's/@1/id/g;s/@2/name/g;s/@3/sex/g;s/@4/score/g' recover.sql 
[root@xiaoya data]# sed -i -r 's/(score.*),/\1/g' recover.sql 
[root@xiaoya data]# cat recover.sql 
UPDATE `students`.`test` 
SET 
  id=1 , 
  name='張三' , 
  sex='男' , 
  score='86'
WHERE 
  id=1 ; 
UPDATE `students`.`test` 
SET 
  id=2 , 
  name='李四' , 
  sex='男' , 
  score='88'
WHERE 
  id=2 ; 
UPDATE `students`.`test` 
SET 
  id=3 , 
  name='王五' , 
  sex='男' , 
  score='90'
WHERE 
  id=3 ; 
UPDATE `students`.`test` 
SET 
  id=4 , 
  name='小紅' , 
  sex='女' , 
  score='92'
WHERE 
  id=4 ; 
UPDATE `students`.`test` 
SET 
  id=5 , 
  name='小芳' , 
  sex='女' , 
  score='96'
WHERE 
  id=5 ;

六、日誌處理到此ok,導入數據看一下code

mysql> unlock tables; 
Query OK, 0 rows affected (0.00 sec) 
   
mysql> source /usr/local/mysql/data/recover.sql 
Query OK, 1 row affected (0.00 sec) 
Rows matched: 1  Changed: 1  Warnings: 0 
   
Query OK, 1 row affected (0.00 sec) 
Rows matched: 1  Changed: 1  Warnings: 0 
   
Query OK, 1 row affected (0.00 sec) 
Rows matched: 1  Changed: 1  Warnings: 0 
   
Query OK, 1 row affected (0.00 sec) 
Rows matched: 1  Changed: 1  Warnings: 0 
   
Query OK, 1 row affected (0.00 sec) 
Rows matched: 1  Changed: 1  Warnings: 0 
   
mysql> select * from test; 
+----+--------+-----+-------+ 
| id | name   | sex | score | 
+----+--------+-----+-------+ 
|  1 | 張三   | 男  | 86    | 
|  2 | 李四   | 男  | 88    | 
|  3 | 王五   | 男  | 90    | 
|  4 | 小紅   | 女  | 92    | 
|  5 | 小芳   | 女  | 96    | 
+----+--------+-----+-------+ 
5 rows in set (0.00 sec)

到這裏數據就完整回來了。將binglog格式設置爲row有利有弊,好處是記錄了每一行的實際變化,在主從複製時也不容易出問題。可是因爲記錄每行的變化,會佔用大量磁盤,主從複製時帶寬佔用會有所消耗。究竟是使用row仍是mixed,須要在實際工做中本身去衡量,但從總體上來講,binglog的格式設置爲row,都是不二的選擇。server

 

 

總結:

一、delete誤刪除和這個原理是同樣的(把binlog在轉換成sql從新插入)

二、解決問題的最好方式是預防問題的發生

方案一:定義別名

[root@xiaoya ~]# alias mysql='mysql -U'

[root@xiaoya ~]# echo "alias mysql='mysql -U'" >>/etc/profile
[root@xiaoya ~]# source /etc/profile

指定登錄-U 後,在mysql裏,執行update和delete操做,若是沒有指定where或limit,則程序拒絕執行。

方案二:在[mysql]段落開啓這個參數:

safe-updates

這樣當咱們在作DML操做時忘記加where條件時,mysqld服務器是不會執行操做的

 

參考:http://www.cnblogs.com/gomysql/p/3582058.html 

爲了方便你們交流,本人開通了微信公衆號,和QQ羣291519319。喜歡技術的一塊兒來交流吧

相關文章
相關標籤/搜索