溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

主從延遲復(fù)制 -- 數(shù)據(jù)恢復(fù)測(cè)試!

發(fā)布時(shí)間:2020-07-31 12:20:08 來(lái)源:網(wǎng)絡(luò) 閱讀:386 作者:insist_way 欄目:MySQL數(shù)據(jù)庫(kù)

寫(xiě)在前面:

????設(shè)想一下,你的線上環(huán)境使用了主從復(fù)制架構(gòu),如果不小心執(zhí)行了,如:drop database db1、drop table tb1,或者說(shuō)delete,update不加where條件的更新,當(dāng)問(wèn)題發(fā)生的時(shí)候,你是不是希望還有補(bǔ)救的機(jī)會(huì)?希望Slave主機(jī)不要重復(fù)Master主機(jī)的執(zhí)行情況?可不可以將這個(gè)有害的SQL跳過(guò)后,繼續(xù)進(jìn)行復(fù)制?答案是:可以的。主從延遲復(fù)制就是實(shí)現(xiàn)這個(gè)功能的


環(huán)境準(zhǔn)備:

????搭建好主從架構(gòu)(筆者采用的傳統(tǒng)的復(fù)制方式)

????設(shè)置好主從延遲變量(如:CHANGE MASTER TO master_delay=180)

????創(chuàng)建好測(cè)試表(在下面詳細(xì)說(shuō)明)


如果執(zhí)行了drop database db1或drop table tb1有害SQL:(drop database和drop table恢復(fù)方式相同,只是影響范圍不同而已)

測(cè)試表:
CREATE TABLE `edusoho_e`.`t1` (
? `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
? `xname` varchar(20) NOT NULL DEFAULT '',
? `address` char(20) NOT NULL DEFAULT '',
? `sex` tinyint(1) NOT NULL DEFAULT '1',
? `hobby` varchar(30) NOT NULL DEFAULT '',
? `age` tinyint(2) DEFAULT '18',
? PRIMARY KEY (`id`),
? KEY `idx_name` (`xname`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

CREATE TABLE `bbs`.`myhash_0` (
? `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
? `c1` int(10) NOT NULL DEFAULT '0',
? `c2` int(10) unsigned DEFAULT NULL,
? `c5` int(10) unsigned NOT NULL DEFAULT '0',
? `c3` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
? `c4` varchar(200) NOT NULL DEFAULT '',
? PRIMARY KEY (`id`),
? KEY `idx_c1` (`c1`),
? KEY `idx_c2` (`c2`)
) ENGINE=InnoDB? DEFAULT CHARSET=utf8

Master主機(jī)在正常的變更數(shù)據(jù):

INSERT INTO `edusoho_e`.`t1` (`xname`, `address`, `hobby`) VALUES ('lzb', '石家莊', 'MySQL');
INSERT INTO `edusoho_e`.`t1` (`xname`, `address`, `hobby`) VALUES ('Python', '北京', '游戲');
INSERT INTO `bbs`.`myhash_0`(c1,c2,c5,c3,c4) VALUES(2,3,4,NOW(),5);
UPDATE `bbs`.`myhash_0` SET id=2 WHERE id=5;


上面的正常數(shù)據(jù)變更還沒(méi)有執(zhí)行完,此時(shí)Master上突然間執(zhí)行了某個(gè)有害SQL:

DROP DATABASE `bbs`;


發(fā)現(xiàn)問(wèn)題后,馬上停止Slave復(fù)制:

mysql> stop slave;


而此時(shí)Master主機(jī)上其他庫(kù)是正常的:

INSERT INTO `edusoho_e`.`t1` (`xname`, `address`, `hobby`) VALUES ('PHP', '深圳', '學(xué)習(xí)');


分析:

drop語(yǔ)句發(fā)生的時(shí)候,drop語(yǔ)句之前的數(shù)據(jù)可能還沒(méi)完全同步至Slave主機(jī)(這很有可能,尤其是你的數(shù)據(jù)量大的情況下),所以,需要分析Master主機(jī)的binlog,找到drop語(yǔ)句發(fā)生的position,使Slave主機(jī)同步至drop語(yǔ)句之前,然后跳過(guò)drop語(yǔ)句,使Slave繼續(xù)同步Master的其他數(shù)據(jù)


分析Master的binlog:

mysqlbinlog -v --base64-output=decode mysql-bin.000001 | grep -i -C 10 --color 'drop'
###?? @3=2
###?? @4=3
###?? @5=1556612931
###?? @6=''
# at 1053
#190430 16:28:51 server id 2? end_log_pos 1084 CRC32 0x7644c8d2???? Xid = 2068
COMMIT/*!*/;
# at 1084
#190430 16:28:51 server id 2? end_log_pos 1180 CRC32 0x8fd4727e???? Query?? thread_id=11??? exec_time=0 error_code=0
SET TIMESTAMP=1556612931/*!*/;
DROP DATABASE `bbs`
/*!*/;
# at 1180
#190430 16:28:52 server id 2? end_log_pos 1262 CRC32 0xcfe6ddb1???? Query?? thread_id=11??? exec_time=0 error_code=0
SET TIMESTAMP=1556612932/*!*/;
BEGIN
/*!*/;
# at 1262
#190430 16:28:52 server id 2? end_log_pos 1323 CRC32 0x539e7626???? Table_map: `edusoho_e`.`t1` mapped to number 312
# at 1323
#190430 16:28:52 server id 2? end_log_pos 1383 CRC32 0xd286a3c0???? Write_rows: table id 312 flags: STMT_END_F


查看詳細(xì)的binlog信息:

mysql> show binlog events in 'mysql-bin.000001' from 1053 limit 10;


跳過(guò)有害SQL,繼續(xù)進(jìn)行復(fù)制:

1、查看當(dāng)前執(zhí)行到的positon

mysql> show slave status\G;
Exec_Master_Log_Pos: 120


2、暫時(shí)將同步延遲關(guān)閉,使Slave立馬同步Master的數(shù)據(jù)

mysql> change master to master_delay=0;


3、同步數(shù)據(jù)至drop語(yǔ)句發(fā)生之前

mysql> start slave until master_log_file='mysql-bin.000001',master_log_pos=1084 user='repliter' password='123456';


4、再次查看執(zhí)行到的position

mysql> show slave status\G;

Exec_Master_Log_Pos: 1084 (drop語(yǔ)句之前的數(shù)據(jù)已經(jīng)同步過(guò)來(lái)了,去Slave相應(yīng)的數(shù)據(jù)表驗(yàn)證下,但是drop語(yǔ)句之后的數(shù)據(jù)還沒(méi)有同步過(guò)來(lái))


現(xiàn)在跳過(guò)有害SQL之后,繼續(xù)Master的數(shù)據(jù)復(fù)制:

mysql> stop slave;

mysql> change master to master_log_pos=1262 [master_delay=180];(可加可不加)

mysql> start slave user='repliter' password='123456';

mysql> show slave status\G;
Exec_Master_Log_Pos: 1414?


去驗(yàn)證drop語(yǔ)句之后的數(shù)據(jù)過(guò)去了沒(méi)
就這樣有害SQL被跳過(guò)了,保留了一份Slave還未被刪除的數(shù)據(jù)備份,之后是做主從切換,還是把數(shù)據(jù)導(dǎo)回到Master就根據(jù)你自己的情況了


筆者這里演示下,將Slave的同名數(shù)據(jù)庫(kù)導(dǎo)回到Master的過(guò)程(如果數(shù)據(jù)量很大的話,建議做主從切換,因?yàn)閷?dǎo)回的成本也許比切換的成本大的多,自行評(píng)估,個(gè)人建議)

1、首先,將Slave的庫(kù)導(dǎo)成SQL文件,這里為bbs_new.sql(一定要有包含創(chuàng)建庫(kù)的語(yǔ)句,要是忘記了,你就自己創(chuàng)建)

2、給導(dǎo)入SQL文件更改權(quán)限
chown mysql.mysql bbs_new.sql

3、mysql -uroot -p bbs -e "SET @@session.sql_log_bin=0;source /root/bbs_new.sql;"?? (一定要加sql_log_bin=0,不然你懂得)


至此,drop database語(yǔ)句,成功跳過(guò)!


如果執(zhí)行了delete from table(不加where條件)或truncate table有害SQL:

Master主機(jī)在正常的變更數(shù)據(jù):

INSERT INTO `edusoho_e`.`t1` (`xname`, `address`, `hobby`,age) VALUES ('Games', '海南', '就是玩',28);?? ?
UPDATE `edusoho_e`.`t1` SET xname='劉備' WHERE id=5;


上面的正常數(shù)據(jù)變更還沒(méi)有執(zhí)行完,此時(shí)Master上突然間執(zhí)行了某個(gè)有害SQL:

DELETE FROM `edusoho_e`.`t1`;


因?yàn)槭莇elete全表數(shù)據(jù),表結(jié)構(gòu)仍在,依據(jù)會(huì)有新數(shù)據(jù)產(chǎn)生和變更:

INSERT INTO `edusoho_e`.`t1` (`xname`, `address`, `hobby`) VALUES ('曹操', '魏國(guó)', '三國(guó)');
UPDATE `edusoho_e`.`t1` SET age=40 WHERE xname='曹操';
DELETE FROM `edusoho_e`.`t1` WHERE xname='lzb';?? #刪除一條不存在的數(shù)據(jù)(不會(huì)產(chǎn)生日志)
UPDATE `edusoho_e`.`t1` SET xname='孫權(quán)' WHERE xname='Python';??? #更新一條不存在的數(shù)據(jù)(不會(huì)產(chǎn)生日志)


發(fā)現(xiàn)問(wèn)題后,馬上停止Slave復(fù)制:

mysql> stop slave;


分析:

此時(shí),Master主機(jī)上其他數(shù)據(jù)庫(kù)、表也是不受影響的。delete全表語(yǔ)句發(fā)生的時(shí)候,delete全表語(yǔ)句之前的數(shù)據(jù)可能還沒(méi)完全同步至Slave主機(jī)(這很有可能,尤其是你的數(shù)據(jù)量大的情況下),所以,需要分析Master主機(jī)的binlog,找到delete全表語(yǔ)句發(fā)生的position,使Slave主機(jī)同步至delete全表語(yǔ)句之前,然后跳過(guò)delete全表語(yǔ)句,使Slave繼續(xù)同步Master的其他數(shù)據(jù)


在Master主機(jī)上根據(jù)時(shí)間分析binlog(因?yàn)楣P者使用的是ROW格式,所以,會(huì)有很多條的delete語(yǔ)句,在delete全表語(yǔ)句之前,極有可能有正常的delete語(yǔ)句,你將分不清哪個(gè)才是該跳過(guò)的有害SQL,所以,問(wèn)題發(fā)生的時(shí)候,一定要盡可能的知道發(fā)生的時(shí)間,對(duì)binlog進(jìn)行分析才能更加有效)


mysqlbinlog -v --base64-output=decode mysql-bin.000001 | grep -i -C 10 --color 'delete from'(筆者自己測(cè)試,生產(chǎn)環(huán)境一定要加時(shí)間篩選)

COMMIT/*!*/;
# at 622
#190505? 8:34:35 server id 2? end_log_pos 704 CRC32 0xd237cd1f? Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=1557016475/*!*/;
BEGIN
/*!*/;
# at 704
#190505? 8:34:35 server id 2? end_log_pos 765 CRC32 0x9335b52a? Table_map: `edusoho_e`.`t1` mapped to number 281
# at 765
#190505? 8:34:35 server id 2? end_log_pos 913 CRC32 0xb6da4487? Delete_rows: table id 281 flags: STMT_END_F
### DELETE FROM `edusoho_e`.`t1`
### WHERE
###?? @1=1
###?? @2='lzb'
###?? @3='石家莊'
###?? @4=1
###?? @5='MySQL'
###?? @6=18
### DELETE FROM `edusoho_e`.`t1`
### WHERE
###?? @1=3
###?? @2='Python'
###?? @3='北京'
###?? @4=1
###?? @5='游戲'
###?? @6=18
### DELETE FROM `edusoho_e`.`t1`
### WHERE
###?? @1=5
###?? @2='劉備'
###?? @3='深圳'
###?? @4=1
###?? @5='學(xué)習(xí)'
###?? @6=18
### DELETE FROM `edusoho_e`.`t1`
### WHERE
###?? @1=7
###?? @2='Games'
###?? @3='海南'
###?? @4=1
###?? @5='就是玩'
###?? @6=28
# at 913
#190505? 8:34:35 server id 2? end_log_pos 944 CRC32 0x215741c7? Xid = 605
COMMIT/*!*/;


查看詳細(xì)的binlog信息:

mysql> show binlog events in 'mysql-bin.000001';(線上的binlog很大,一定要加from做篩選)
+------------------+------+-------------+-----------+-------------+---------------------------------------+
| Log_name???????? | Pos? | Event_type? | Server_id | End_log_pos | Info????????????????????????????????? |
+------------------+------+-------------+-----------+-------------+---------------------------------------+
| mysql-bin.000001 |??? 4 | Format_desc |???????? 2 |???????? 120 | Server ver: 5.6.16-log, Binlog ver: 4 |
| mysql-bin.000001 |? 120 | Query?????? |???????? 2 |???????? 202 | BEGIN???????????????????????????????? |
| mysql-bin.000001 |? 202 | Table_map?? |???????? 2 |???????? 263 | table_id: 281 (edusoho_e.t1)????????? |
| mysql-bin.000001 |? 263 | Write_rows? |???????? 2 |???????? 328 | table_id: 281 flags: STMT_END_F?????? |
| mysql-bin.000001 |? 328 | Xid???????? |???????? 2 |???????? 359 | COMMIT /* xid=587 */????????????????? |
| mysql-bin.000001 |? 359 | Query?????? |???????? 2 |???????? 441 | BEGIN???????????????????????????????? |
| mysql-bin.000001 |? 441 | Table_map?? |???????? 2 |???????? 502 | table_id: 281 (edusoho_e.t1)????????? |
| mysql-bin.000001 |? 502 | Update_rows |???????? 2 |???????? 591 | table_id: 281 flags: STMT_END_F?????? |
| mysql-bin.000001 |? 591 | Xid???????? |???????? 2 |???????? 622 | COMMIT /* xid=596 */????????????????? |
| mysql-bin.000001 |? 622 | Query?????? |???????? 2 |???????? 704 | BEGIN???????????????????????????????? |
| mysql-bin.000001 |? 704 | Table_map?? |???????? 2 |???????? 765 | table_id: 281 (edusoho_e.t1)????????? |
| mysql-bin.000001 |? 765 | Delete_rows |???????? 2 |???????? 913 | table_id: 281 flags: STMT_END_F?????? |
| mysql-bin.000001 |? 913 | Xid???????? |???????? 2 |???????? 944 | COMMIT /* xid=605 */????????????????? |
| mysql-bin.000001 |? 944 | Query?????? |???????? 2 |??????? 1026 | BEGIN???????????????????????????????? |
| mysql-bin.000001 | 1026 | Table_map?? |???????? 2 |??????? 1087 | table_id: 281 (edusoho_e.t1)????????? |
| mysql-bin.000001 | 1087 | Write_rows? |???????? 2 |??????? 1150 | table_id: 281 flags: STMT_END_F?????? |
| mysql-bin.000001 | 1150 | Xid???????? |???????? 2 |??????? 1181 | COMMIT /* xid=614 */????????????????? |
| mysql-bin.000001 | 1181 | Query?????? |???????? 2 |??????? 1263 | BEGIN???????????????????????????????? |
| mysql-bin.000001 | 1263 | Table_map?? |???????? 2 |??????? 1324 | table_id: 281 (edusoho_e.t1)????????? |
| mysql-bin.000001 | 1324 | Update_rows |???????? 2 |??????? 1416 | table_id: 281 flags: STMT_END_F?????? |
| mysql-bin.000001 | 1416 | Xid???????? |???????? 2 |??????? 1447 | COMMIT /* xid=623 */????????????????? |
+------------------+------+-------------+-----------+-------------+---------------------------------------+


跳過(guò)有害SQL,繼續(xù)進(jìn)行復(fù)制:

1、暫時(shí)將同步延遲關(guān)閉,使Slave立馬同步Master的數(shù)據(jù)

mysql> change master to master_delay=0;


2、同步數(shù)據(jù)至drop語(yǔ)句發(fā)生之前

mysql> start slave until master_log_file='mysql-bin.000001',master_log_pos=622 user='repliter' password='123456';


3、再次查看執(zhí)行到的position

mysql> show slave status\G;

Exec_Master_Log_Pos: 622? (delete全表語(yǔ)句之前的數(shù)據(jù)已經(jīng)同步過(guò)來(lái)了,去Slave相應(yīng)的數(shù)據(jù)表驗(yàn)證下,但是delete全表語(yǔ)句之后的數(shù)據(jù)還沒(méi)有同步過(guò)來(lái))


現(xiàn)在跳過(guò)有害SQL之后,繼續(xù)Master的數(shù)據(jù)復(fù)制:

mysql> stop slave;

mysql> change master to master_log_pos=1026 [master_delay=180];(可加可不加)

mysql> start slave user='repliter' password='123456';

mysql> show slave status\G;
Exec_Master_Log_Pos: 1447


去驗(yàn)證delete全表語(yǔ)句之后的數(shù)據(jù)過(guò)去了沒(méi)
就這樣有害SQL被跳過(guò)了,保留了一份Slave還未被刪除的數(shù)據(jù)備份,之后是做主從切換,還是把數(shù)據(jù)導(dǎo)回到Master就根據(jù)你自己的情況了


筆者這里演示下,將Slave的同名數(shù)據(jù)庫(kù)導(dǎo)回到Master的過(guò)程(如果數(shù)據(jù)量很大的話,建議做主從切換,因?yàn)閷?dǎo)回的成本也許比切換的成本大的多)

如果你的數(shù)據(jù)表數(shù)據(jù)量較小,可以在上述until語(yǔ)句執(zhí)行完之后,將Master的數(shù)據(jù)表加上全局寫(xiě)鎖,然后將Slave主機(jī)上的數(shù)據(jù)同步過(guò)去,因?yàn)閿?shù)據(jù)表小,對(duì)業(yè)務(wù)影響也不會(huì)太大


將Master主機(jī)上的數(shù)據(jù)表加上寫(xiě)鎖:(如果你知道你的數(shù)據(jù)表pk值不會(huì)被插入,而是依靠自增生成,那么你可能需要先將表清空,導(dǎo)入舊數(shù)據(jù)后,再導(dǎo)入新數(shù)據(jù),這樣才能保證數(shù)據(jù)的一致性)

LOCK TABLE `edusoho_e`.`t1` WRITE;


然后再Slave主機(jī)上把until語(yǔ)句之前的數(shù)據(jù)導(dǎo)出來(lái):

INSERT INTO `t1` VALUES (1,'lzb','石家莊',1,'MySQL',18),(3,'Python','北京',1,'游戲',18),(5,'劉備','深圳',1,'學(xué)習(xí)',18),(7,'Games','海南',1,'就是玩',28);


切換到Master:

mysql> show master status\G;
*************************** 1. row ***************************
???????????? File: mysql-bin.000001
???????? Position: 1447


SET @@session.sql_log_bin=0;? (一定要做,具體原因應(yīng)該都知道)


把數(shù)據(jù)導(dǎo)回去(如果是SQL文件,則執(zhí)行source導(dǎo)入)

INSERT INTO `t1` VALUES (1,'lzb','石家莊',1,'MySQL',18),(3,'Python','北京',1,'游戲',18),(5,'劉備','深圳',1,'學(xué)習(xí)',18),(7,'Games','海南',1,'就是玩',28);


mysql> show master status\G;
*************************** 1. row ***************************
???????????? File: mysql-bin.000001
???????? Position: 1447


釋放鎖:

UNLOCK TABLES;

至此,delete 全表語(yǔ)句,成功跳過(guò)!


如果執(zhí)行了update table(不加限制條件)有害SQL:

測(cè)試表:
CREATE TABLE `orders` (
? `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
? `xname` varchar(10) NOT NULL DEFAULT '' COMMENT '用戶名稱(chēng)',
? `chongzhi` int(11) NOT NULL DEFAULT '0' COMMENT '充值金額',
? `amount` int(11) NOT NULL DEFAULT '0' COMMENT '剩余金額',
? PRIMARY KEY (`id`)
) ENGINE=InnoDB? DEFAULT CHARSET=utf8 COMMENT='用戶訂單表'


正常的Master數(shù)據(jù)變更:
INSERT INTO `edusoho_e`.`orders`(xname,chongzhi,amount) VALUES('鄭千次',10000,100);
INSERT INTO `edusoho_e`.`orders`(xname,chongzhi,amount) VALUES('孫悟空',200,600);
INSERT INTO `edusoho_e`.`orders`(xname,chongzhi,amount) VALUES('柯南',666,888);
INSERT INTO `edusoho_e`.`orders`(xname,chongzhi,amount) VALUES('我',1,0);
UPDATE `edusoho_e`.`orders` SET chongzhi=chongzhi+1000 WHERE id=3;
UPDATE `edusoho_e`.`orders` SET amount=amount-200 WHERE id=5;
UPDATE `edusoho_e`.`orders` SET amount=amount-100;


此時(shí),線上有一張用戶訂單表,執(zhí)行了一條不加WHERE條件的UPDATE語(yǔ)句:

UPDATE `edusoho_e`.`orders` SET chongzhi=chongzhi+1000;

執(zhí)行過(guò)后,用戶很高興,因?yàn)闆](méi)充錢(qián),白得了1000塊;但是你的老板,絕對(duì)恨不得揍死你,為了不被揍,所以,你得趕緊恢復(fù)你的數(shù)據(jù)


發(fā)現(xiàn)問(wèn)題后,馬上停止Slave復(fù)制:

mysql> stop slave;


分析:

發(fā)現(xiàn)問(wèn)題之后,馬上對(duì)Master加寫(xiě)鎖,因?yàn)榇藭r(shí)數(shù)據(jù)雖然存在,但是已經(jīng)是錯(cuò)誤的數(shù)據(jù);然后確定有害SQL的position,然后跳過(guò)它,繼續(xù)Master的復(fù)制


LOCK TABLE `edusoho_e`.`orders` WRITE;


在Master主機(jī)上根據(jù)時(shí)間分析binlog(因?yàn)楣P者使用的是ROW格式,所以,會(huì)有很多條的update語(yǔ)句,如果在update不加限制條件語(yǔ)句之前,也有正常的update語(yǔ)句,你將分不清哪個(gè)才是該跳過(guò)的有害SQL,所以,問(wèn)題發(fā)生的時(shí)候,一定要盡可能的知道發(fā)生的時(shí)間,對(duì)binlog進(jìn)行分析才能更加有效)


分析Master日志,找到執(zhí)行的問(wèn)題SQL發(fā)生的position:
mysqlbinlog -v --base64-output=decode mysql-bin.000001 | grep -i -C 10 --color 'update'
COMMIT/*!*/;
# at 3554
#190505 10:04:20 server id 2? end_log_pos 3636 CRC32 0xd95ad4e9?? Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=1557021860/*!*/;
BEGIN
/*!*/;
# at 3636
#190505 10:04:20 server id 2? end_log_pos 3695 CRC32 0xa8208a81?? Table_map: `edusoho_e`.`orders` mapped to number 282
# at 3695
#190505 10:04:20 server id 2? end_log_pos 3897 CRC32 0xdb6fe2c1?? Update_rows: table id 282 flags: STMT_END_F
### UPDATE `edusoho_e`.`orders`
### WHERE
###?? @1=1
###?? @2='鄭千次'
###?? @3=10000
###?? @4=100
### SET
###?? @1=1
###?? @2='鄭千次'
###?? @3=11000
###?? @4=100
### UPDATE `edusoho_e`.`orders`
### WHERE
###?? @1=3
###?? @2='孫悟空'
###?? @3=1200
###?? @4=600
### SET
###?? @1=3
###?? @2='孫悟空'
###?? @3=2200
###?? @4=600
### UPDATE `edusoho_e`.`orders`
### WHERE
###?? @1=5
###?? @2='柯南'
###?? @3=666
###?? @4=688
### SET
###?? @1=5
###?? @2='柯南'
###?? @3=1666
###?? @4=688
### UPDATE `edusoho_e`.`orders`
### WHERE
###?? @1=7
###?? @2='我'
###?? @3=1
###?? @4=0
### SET
###?? @1=7
###?? @2='我'
###?? @3=1001
###?? @4=0

mysql> show binlog events in 'mysql-bin.000001' from 3554;
+------------------+------+-------------+-----------+-------------+----------------------------------+
| Log_name???????? | Pos? | Event_type? | Server_id | End_log_pos | Info???????????????????????????? |
+------------------+------+-------------+-----------+-------------+----------------------------------+
| mysql-bin.000001 | 3554 | Query?????? |???????? 2 |??????? 3636 | BEGIN??????????????????????????? |
| mysql-bin.000001 | 3636 | Table_map?? |???????? 2 |??????? 3695 | table_id: 282 (edusoho_e.orders) |
| mysql-bin.000001 | 3695 | Update_rows |???????? 2 |??????? 3897 | table_id: 282 flags: STMT_END_F? |
| mysql-bin.000001 | 3897 | Xid???????? |???????? 2 |??????? 3928 | COMMIT /* xid=893 */???????????? |
+------------------+------+-------------+-----------+-------------+----------------------------------+
4 rows in set (0.00 sec)


跳過(guò)有害SQL,繼續(xù)進(jìn)行復(fù)制:

1、和問(wèn)題發(fā)生人員溝通,確認(rèn)update是怎樣執(zhí)行的

在Master上執(zhí)行:

SET @@session.sql_log_bin=0;(一定要加,不然你懂得)
UPDATE `edusoho_e`.`orders` SET chongzhi=chongzhi-1000;
此時(shí),Master和SLave的數(shù)據(jù)都恢復(fù)了一致,只要Slave跳過(guò)有害的UPDATE語(yǔ)句就可以了


2、跳過(guò)有害SQL,繼續(xù)復(fù)制

mysql> change master to master_log_pos=3928 [master_delay=180];(可加可不加)


3、start slave user='repliter' password='123456';


4、釋放表的寫(xiě)鎖

UNLOCK TABLES;


至此,update全表語(yǔ)句,成功跳過(guò)!


題外:

本文是筆者根據(jù)自己的理解,設(shè)想線上可能發(fā)生的部分問(wèn)題后,針對(duì)性的利用 master_delay 參數(shù)特性,進(jìn)行數(shù)據(jù)恢復(fù)做的測(cè)試,并沒(méi)有經(jīng)過(guò)任何的實(shí)戰(zhàn)檢測(cè)。一方面,僅為廣大同行做個(gè)參考;另一方面,記錄筆者自己的心得和針對(duì)問(wèn)題解決的思路做個(gè)總結(jié),當(dāng)問(wèn)題真正發(fā)生的時(shí)候,有個(gè)方向可以進(jìn)行參考,而不至于手忙腳亂,不知所措,所以,對(duì)其中有誤之處和理解不到位的地方,望請(qǐng)下方留言指正,不勝感激!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI