单表恢复

前言

单表恢复有两种情况:
1、主库单表恢复
2、从库单表恢复
下面就从这两种情况说一下解决思路和步骤

1、主库单库恢复

1.1 恢复思路

因为mysqlbinlog 对于单表过滤效果不好,可以通过对库的恢复然后跑binlog。看情况是否直接从备份机拉取整库备份。
如果单库数据量(相对全库较小),可从故意延迟从库mysqldump,如果单库数据量并不小,从远程备份机拉取全备

1.2 定位问题SQL

     确定错误SQL类型:误操作 drop table,还是是dml 没有where条件
     确定误操作大致时间
mysqlbinlog -vv -d test  --start-datetime='xx'  --stop-datetime='xx' mysqllogbin.000004 |egrep -B4 "INSERT|UPDATE|DELETE" |egrep -B4 "\`t3\`"


# at A
#131205 20:55:08 server id 18984603  end_log_pos 20393779     Query    thread_id=16296016    exec_time=0    error_code=0
SET TIMESTAMP=1386248108/*!*/;
BEGIN
/*!*/;
# at 20393779
#131205 20:55:08 server id 18984603  end_log_pos 20394211     Query    thread_id=16296016    exec_time=0    error_code=0
SET TIMESTAMP=1386248108/*!*/;
update table tablename set names='xxxx';
# at 20394211
#131205 20:55:08 server id 18984603  end_log_pos 20394238     Xid = 92465981
COMMIT/*!*/;
# at B

1.3  单库备份恢复

    # mysqldump -uroot -p123123 -S /mysqldata/mysql.sock --single-transaction --routines --events --master-data=2 test t1 >/tmp/t1.sql
    # head -30 /tmp/t1.sql |egrep CHANGE , 得到位点C
    # mysqlbinlog -vv  -d test  --start-position=C  --stop-position=A  mysqlbinlog--xxx >a.sql      
    # mysqlbinlog --vv -d test --start-positoon=B  --stop-position=xx   mysqlbinlog-xx  >b.sql

1.4 全库备份恢复

    全库恢复
    恢复binlog,跳过错误SQL


2、从库单表快速恢复

2.1 情景描述

2.2 恢复过程

1. 从库发现复制异常,stop slave 
2. 主库用mysqldump导出单表,注意,单表是导出开始时刻数据,master-data 记录位点A
3. 从库恢复单表
4. 修改my.cnf ,开启复制过滤、skip-slave-start 重启数据库
5. start slave until A, 直到追平到主库mysqldump时刻
6. 修改my.cnf ,去掉复制过滤,重启,start slave

2.3 实验模拟

主库建表插入数据
08:37:59 (none)> create database test ;
11:02:12 (none)> use test;
11:02:15 test> create table t1 (id int primary key ,age int );
11:03:14 test> create table t2 (id int primary key,name varchar(20));
11:02:48 test> insert into t1 values (1,1),(2,2);
11:03:39 test> insert into t2 values(1,'a'),(2,'b');


从库模拟误操作:

mysql> drop table t1;


主库正常继续操作

11:25:38 test> insert into t1 values (3,3);

11:27:25 test> insert into t2 values (3,'c');


从库开始报错
mysql> show slave status G
*************************** 1. row ***************************
                  Last_Errno: 1146
                  Last_Error: Error executing row event: 'Table 'test.t1' doesn't exist'
              Last_SQL_Error: Error executing row event: 'Table 'test.t1' doesn't exist'

mysql> stop slave ;


主库继续操作,并单表导出,查看位点

[root@ser1 mysqldata]# >/tmp/t1.sql
[root@ser1 mysqldata]# mysqldump -uroot -p123123 -S /mysqldata/mysql.sock --single-transaction --routines --events --master-data=2 test t1 >/tmp/t1.sql
[root@ser1 mysqldata]# head -30 /tmp/t1.sql |egrep CHANGE
-- CHANGE MASTER TO MASTER_LOG_FILE='binlog.000054', MASTER_LOG_POS=10593;
[root@ser1 ~]# scp /tmp/t1.sql root@192.168.234.130:/tmp/

11:32:27 test> insert into t1 values (4,4);
11:27:35 test> insert into t2 values (4,'d');   



从库恢复单表
[root@ser2 ~]# mysql -uroot -p123123 test </tmp/t1.sql 
mysql> select * from t1;           //数据是备份时刻 t1的最新数据
+----+------+
| id | age  |
+----+------+
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
+----+------+
mysql> select * from test.t2;     //数据是从库复制错误时刻的点,恢复后 t1 表新于 t2 表
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
+----+------+

4 rows in set (0.00 sec)

开启复制过滤,重启

[root@ser2 ~]# cat /etc/my.cnf |egrep -i "Repl*" -B1
skip-slave-start
replicate_wild_ignore_table=test.t1     //复制忽略test.t1这个表

[root@ser2 ~]# service mysqld restart
Shutting down MySQL..                                      [  OK  ]
Starting MySQL.                                                  [  OK  ]

# 开启复制过滤主从执行到备份点,让其他表执行到一致位点。
mysql> START SLAVE UNTIL MASTER_LOG_FILE = 'binlog.000054', MASTER_LOG_POS=10593;

mysql> show slave status G
*************************** 1. row ***************************
              Slave_IO_State: Waiting for master to send event
              Master_Log_File: binlog.000054
            Slave_IO_Running: Yes           // IO线程连接正常
            Slave_SQL_Running: No         //执行到这个位点就不再执行了
          Exec_Master_Log_Pos: 10593    //执行到了指定的点

mysql> select * from test.t2;           //t2执行到备份开始点,t1/t2 时刻一致了
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
|  3 | c    |
+----+------+

6 rows in set (0.00 sec)


关闭复制过滤,正常启动slave

[root@ser2 ~]# vim /etc/my.cnf
#replicate_wild_ignore_table=test.t1    //关闭复制过滤表
[root@ser2 ~]# service mysqld restart


mysql> start slave;

mysql> select * from t1;
+----+------+
| id | age  |
+----+------+
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
|  4 |    4 |
+----+------+

mysql> select * from t2;
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
|  3 | c    |
|  4 | d    |
+----+------+








原文地址:https://www.cnblogs.com/jesper/p/7505855.html