記一次生產(chǎn)事故:一年的數(shù)據(jù)被刪除了
故事開始
快要下班了,心情是這樣的。

突然電話響了,一看電話號(hào)碼是項(xiàng)目甲方負(fù)責(zé)人的號(hào)碼

菊花一緊,難道出什么問題了,硬著頭皮接通了電話。
@####@,你們程序怎么回事 ,某個(gè)業(yè)務(wù)的數(shù)據(jù)界面一條都查詢不到了。。。。。
我們馬上排查一下,看看那什么情況(心理活動(dòng):尼瑪,尼瑪,我怎么知道啊)???
哦豁、哦豁、數(shù)據(jù)庫里也沒了,用戶做了一年的任務(wù)數(shù)據(jù)都沒了,我尼瑪!!!!
甲方要求今天必須恢復(fù)數(shù)據(jù),什么問題導(dǎo)致的你們后面自己排查去。
好好好,是是是
(恢復(fù)數(shù)據(jù)不都是小菜一碟的事畢竟我們數(shù)據(jù)庫每天凌晨有定時(shí)全量備份,也開了binlog日志的,哈哈,這難不倒我)
恢復(fù)數(shù)據(jù)沒問題啊

binlog里面把刪除語句找出來,逆向改成插入語句不就恢復(fù)了,這事不就歐了。
說干就干,先讓公司現(xiàn)場(chǎng)運(yùn)維同事幫忙把binlog拷貝出來
開始搞binlog,通過命令: mysqlbinlog --no-defaults -vv --base64-output=decode-rows --start-datetime='2024-12-30 16:49:35' --stop-datetime='2024-12-30 17:00:00' mysql-bin.000103 >outsql1.sql;找出對(duì)應(yīng)時(shí)間點(diǎn)的語句刪除。

找到刪除語句還是很順利,但是

binlog 中的刪除語句只有被刪除數(shù)據(jù)的ID,沒有刪除數(shù)據(jù)的詳細(xì)數(shù)據(jù),tmd 這怎么搞(后面再說原因,先恢復(fù)數(shù)據(jù)要緊)
沒辦法只能拷貝全量備份文件了


說明:
數(shù)據(jù)丟失的原因:程序缺陷導(dǎo)致,一個(gè)平常不用的功能,剛好年底了用到了
binlog里面為啥只有刪除數(shù)據(jù)的ID沒有詳情:因?yàn)锽inlog 格式設(shè)置的是“Mixed”
總結(jié):
1、設(shè)Binlog模式要慎重,還得的按照自己項(xiàng)目實(shí)際情況去設(shè)置 binlog 類型,不然可能會(huì)對(duì)恢復(fù)數(shù)據(jù)造成麻煩。
binlog 有三種格式:
-
- Statement(Statement-Based Replication,SBR):每一條會(huì)修改數(shù)據(jù)的 SQL 都會(huì)記錄在 binlog 中。
- Row(Row-Based Replication,RBR):不記錄 SQL 語句上下文信息,僅保存哪條記錄被修改。
- Mixed(Mixed-Based Replication,MBR):Statement 和 Row 的混合體。
Statement
Statement 模式只記錄執(zhí)行的 SQL,不需要記錄每一行數(shù)據(jù)的變化,因此極大的減少了 binlog 的日志量,避免了大量的 IO 操作,提升了系統(tǒng)的性能。(比如update user set name="張三" where id >1 and id <10000,假設(shè)被修改的數(shù)據(jù)有2000條,那么Row的日志量就是2000條,而Statement只是這條sql語句一條日志而已,所以Statement的日志量相對(duì)Row會(huì)少很多)
但是,正是由于 Statement 模式只記錄 SQL,而如果一些 SQL 中 包含了函數(shù),那么可能會(huì)出現(xiàn)執(zhí)行結(jié)果不一致的情況。比如說 uuid() 函數(shù),每次執(zhí)行的時(shí)候都會(huì)生成一個(gè)隨機(jī)字符串,在 master 中記錄了 uuid,當(dāng)同步到 slave 之后,再次執(zhí)行,就得到另外一個(gè)結(jié)果了。
所以使用 Statement 格式會(huì)出現(xiàn)一些數(shù)據(jù)一致性問題。
Row
從 MySQL5.1.5 版本開始,binlog 引入了 Row 格式,Row 格式不記錄 SQL 語句上下文相關(guān)信息,僅僅只需要記錄某一條記錄被修改成什么樣子了。
Row 格式的日志內(nèi)容會(huì)非常清楚地記錄下每一行數(shù)據(jù)修改的細(xì)節(jié),這樣就不會(huì)出現(xiàn) Statement 中存在的那種數(shù)據(jù)無法被正常復(fù)制的情況。
不過 Row 格式也有一個(gè)很大的問題,那就是日志量太大了,特別是批量 update、整表 delete、alter 表等操作,由于要記錄每一行數(shù)據(jù)的變化,此時(shí)會(huì)產(chǎn)生大量的日志,大量的日志也會(huì)帶來 IO 性能問題。
Mixed
從 MySQL5.1.8 版開始,MySQL 又推出了 Mixed 格式,這種格式實(shí)際上就是 Statement 與 Row 的結(jié)合。
在 Mixed 模式下,系統(tǒng)會(huì)自動(dòng)判斷 該 用 Statement 還是 Row:一般的語句修改使用 Statement 格式保存 binlog;對(duì)于一些 Statement 無法準(zhǔn)確完成主從復(fù)制的操作,則采用 Row 格式保存 binlog。
Mixed 模式中,MySQL 會(huì)根據(jù)執(zhí)行的每一條具體的 SQL 語句來區(qū)別對(duì)待記錄的日志格式,也就是在 Statement 和 Row 之間選擇一種。
2、全量備份是必要的,這次就靠全量備份活過來了,binlog的增量備份也是很必要的可以盡量減少數(shù)據(jù)丟失,但是要注意binlog的模式設(shè)置。
3、cat testdb_all.sql |grep -E ‘INSERT INTO `personchangeinfo`’ > personchangeinfo1.sql ; 這個(gè)命令很實(shí)用,可以從大文件里面查找匹配內(nèi)容并輸出到新文件
4、用mysqldump 備份的文件,壓縮比很可觀的,別忘了壓縮。

浙公網(wǎng)安備 33010602011771號(hào)