溫馨提示×

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

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

mysql刪庫不跑路

發(fā)布時(shí)間:2020-08-10 18:33:30 來源:ITPUB博客 閱讀:153 作者:sery 欄目:MySQL數(shù)據(jù)庫

上周夜里,一個(gè)奢侈品電商網(wǎng)站的程序員手抖,把阿里云rds的某個(gè)庫給刪了,當(dāng)時(shí)都11點(diǎn)多了,心中一萬個(gè)羊駝在奔騰,還好,沒讓我出手,小弟就把它給恢復(fù)了。昨天上午,又一個(gè)網(wǎng)站的程序員手抖,給一個(gè)還要用的庫給刪了。這也不能全怪他,本來計(jì)劃遷移數(shù)據(jù)的,因?yàn)閿?shù)據(jù)庫太大,進(jìn)行分拆,把大庫變小。遷移走了一些,就要?jiǎng)h掉遷走的,這樣以利于后邊遷移加快速度。


也許有人說,這是管理上的問題,的確如此。應(yīng)該加強(qiáng)權(quán)限管理,并制度相應(yīng)的技術(shù)保障措施及流程規(guī)范。有相應(yīng)的保障或者措施,雖然不能完全杜絕誤操作,但起碼會(huì)大大降低概率。我為啥經(jīng)常遇到這種事情,來回折騰呢?主要是這些年,我做的是外圍支援,以技術(shù)層面為主,不參與更多的事務(wù)。當(dāng)然,對(duì)于大多數(shù)規(guī)模有限的公司來說,完善流程制度也難于落實(shí)。因此,雖然遇到不少麻煩,總結(jié)一下寫出來,應(yīng)該對(duì)其他人有所幫助。


恢復(fù)的第一要?jiǎng)?wù),是找備份。還好,有一個(gè)201869日的備份存在。本來一直都在自動(dòng)備份的,后來由于要遷移,而且據(jù)說近期夜間備份時(shí),非常占用資源,負(fù)載老高,到上午上班時(shí),備份壓縮那一步還沒有結(jié)束,就把備份給停了。

mysql刪庫不跑路

這是遷移部分?jǐn)?shù)據(jù)后,還刪掉遷走庫以后的容量,確實(shí)有點(diǎn)大。像這種情況,要么分拆,要么做增量備份,把自動(dòng)備份停了的做法,風(fēng)險(xiǎn)實(shí)在是大。


為了降低風(fēng)險(xiǎn),在恢復(fù)前最好做一次全庫備份,萬一搞出問題,還能回得去。基于這個(gè)想法,開始執(zhí)行備份。執(zhí)行了兩個(gè)小時(shí),還沒見動(dòng)靜,也無法評(píng)估大概要多長時(shí)間,其它人等不及了,同時(shí)備份也影響其它業(yè)務(wù)的正常運(yùn)行,因此只好直接停止備份。


開干前先算一卦,測一下吉兇。得詬之坎卦,三爻、四爻、上爻動(dòng),好在用神旺相,有修復(fù)的希望。導(dǎo)入數(shù)據(jù)步驟如下:

◆備份文件解包,并打開文件看一眼內(nèi)容

[root@db-209 mysql_bk_dir]# pwd

/data/databk/mysql_bk_dir

[root@db-209 mysql_bk_dir]# tar zxvf mobile7_quanzhen20180609.tgz

mobile7_quanzhen20180609.sql

[root@db-209 mysql_bk_dir]# more mobile7_quanzhen20180609.sql

-- MySQL dump 10.13 Distrib 5.5.29, for Linux (x86_64)

--

-- Host: localhost Database: mobile7_quanzhen

-- ------------------------------------------------------

-- Server version 5.5.29-log


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;

/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;

/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;

/*!40101 SET NAMES utf8 */;

/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;

/*!40103 SET TIME_ZONE='+00:00' */;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;

/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;

/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;

/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;


--

-- Table structure for table `quanzhen_aboutegg`

--


DROP TABLE IF EXISTS `quanzhen_aboutegg`;

/*!40101 SET @saved_cs_client = @@character_set_client */;

/*!40101 SET character_set_client = utf8 */;

CREATE TABLE `quanzhen_aboutegg` (

`id` int(8) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',

`uid` mediumint(8) unsigned NOT NULL COMMENT '會(huì)員ID',

`content` text NOT NULL COMMENT '內(nèi)容',

`title` varchar(100) NOT NULL COMMENT '標(biāo)題',

`sort` int(5) unsigned NOT NULL COMMENT '排序',

`status` tinyint(1) unsigned NOT NULL COMMENT '0不顯示,1顯示',

`updated` int(8) NOT NULL COMMENT '修改時(shí)間',

`created` int(8) NOT NULL COMMENT '增加時(shí)間',

PRIMARY KEY (`id`)

) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COMMENT='關(guān)于金蛋系統(tǒng)說明表';

/*!40101 SET character_set_client = @saved_cs_client */;

……………………………省略若干……………………………………….

◆創(chuàng)建數(shù)據(jù)庫并導(dǎo)入數(shù)據(jù)

mysql> create database mobile7_quanzhen;

mysql> use mobile7_quanzhen;

mysql> source /data/databk/mysql_bk_dir/mobile7_quanzhen20180609.sql;

上述操作很順利,基本沒啥障礙。


重點(diǎn)部分來了,需要確定恢復(fù)到什么位置。這些信息從哪里得到呢?數(shù)據(jù)庫存儲(chǔ)目錄里邊的二進(jìn)制日志。

[root@db-209 mysql_db]# pwd

/data/mysql_db

[root@db-209 mysql_db]# ls -al |grep mysql-bin

-rw-rw---- 1 mysql mysql 1073744253 Jun 17 01:20 mysql-bin.000856

-rw-rw---- 1 mysql mysql 106606897 Jun 17 04:02 mysql-bin.000857

-rw-rw---- 1 mysql mysql 1073742155 Jun 18 02:22 mysql-bin.000858

-rw-rw---- 1 mysql mysql 58702046 Jun 18 04:02 mysql-bin.000859

-rw-rw---- 1 mysql mysql 1073745791 Jun 19 03:20 mysql-bin.000860

-rw-rw---- 1 mysql mysql 24180628 Jun 19 04:02 mysql-bin.000861

-rw-rw---- 1 mysql mysql 1073741973 Jun 20 00:31 mysql-bin.000862

-rw-rw---- 1 mysql mysql 172478749 Jun 20 04:02 mysql-bin.000863

-rw-rw---- 1 mysql mysql 1073741972 Jun 20 23:11 mysql-bin.000864

-rw-rw---- 1 mysql mysql 172554351 Jun 21 04:02 mysql-bin.000865

-rw-rw---- 1 mysql mysql 150489 Jun 21 04:02 mysql-bin.000866

-rw-rw---- 1 mysql mysql 747165143 Jun 21 16:11 mysql-bin.000867

-rw-rw---- 1 mysql mysql 228 Jun 21 04:02 mysql-bin.index

從輸出可知,二進(jìn)制文件并不多,最舊的一個(gè)的時(shí)間戳是617號(hào),10號(hào)到16號(hào)的丟失了。只保留最近5天的日志,這個(gè)是由mysql選項(xiàng)文件/etc/my.cnf設(shè)定的,其內(nèi)容為:

[root@db-209 mysql_db]# more /etc/my.cnf

……………………………………….省略若干…………………………

[mysqld]

port = 3306

socket = /tmp/mysql.sock

datadir = /data/mysql_db

#log_bin_trust_function_creators = 1

skip-external-locking

skip-name-resolve

wait_timeout=10

interactive_timeout=300

connect_timeout=300

max_connections = 2000

max_connect_errors = 50

tmp_table_size = 128M

expire_logs_days = 5

slave-skip-errors = 1690,1062

# Try number of CPU's*2 for thread_concurrency

thread_concurrency = 8

slow_query_log = 1

slow_query_log_file=/data/mysql_db/slow.log

………………………………省略若干……………………………………………….

雖然是五天的數(shù)據(jù),但文件卻是好幾個(gè)。為啥不設(shè)置保留天數(shù)多一些呢?還不是因?yàn)檫@個(gè)機(jī)器太老,資源有限。把風(fēng)險(xiǎn)告知其他讓你,申明可能有幾天的的數(shù)據(jù)會(huì)丟失。大家一致認(rèn)同,能恢復(fù)多少算多少,總比沒有強(qiáng)。


詢問了執(zhí)行誤操作的程序員,大概是哪個(gè)時(shí)間執(zhí)行的drop操作?回答說是620號(hào)上午10點(diǎn)過幾分。有了這個(gè)參照點(diǎn),再查看二進(jìn)制日志文件的時(shí)間戳,就可定位到文件“mysql-bin.000864”,確定這個(gè)文件的原因是文件“mysql-bin.000863”的最后寫入時(shí)間是“6204:02”,這樣一來范圍就縮小很多。當(dāng)然,也可以不管這些,用通配符,搜索所有二進(jìn)制日志文件,確定恢復(fù)點(diǎn)。我決定以時(shí)間點(diǎn)來進(jìn)行恢復(fù),具體的操作如下:

◆確定恢復(fù)的時(shí)間點(diǎn)

[root@db-209 mysql_db]# pwd

/data/mysql_db

[root@db-209 mysql_db]# /usr/local/mysql/bin/mysqlbinlog -v --base64-output=DECODE-ROWS mysql-bin.000864|grep -C 10 -i drop

INSERT INTO `quanzhen_everydaycpdcontrol` (todaytime,uid,todaynum) VALUES (1529424000,661526,3)

/*!*/;

# at 393124773

#180620 10:08:44 server id 21 end_log_pos 393124800 Xid = 629128212

COMMIT/*!*/;

# at 393124800

#180620 10:08:44 server id 21 end_log_pos 393124901 Query thread_id=85127174 exec_time=0 error_code=0

SET TIMESTAMP=1529460524/*!*/;

/*!\C latin1 *//*!*/;

SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=33/*!*/;

drop database mobile7_quanzhen

/*!*/;

# at 393124901

#180620 10:08:44 server id 21 end_log_pos 393124989 Query thread_id=85160078 exec_time=0 error_code=0

SET TIMESTAMP=1529460524/*!*/;

/*!\C utf8 *//*!*/;

SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;

BEGIN

/*!*/;

# at 393124989

#180620 10:08:44 server id 21 end_log_pos 393125017 Intvar

--

INSERT INTO `quanzhen_everydaycpdcontrol` (todaytime,uid,todaynum) VALUES (1529424000,399677,4)

/*!*/;

# at 399014378

#180620 10:13:27 server id 21 end_log_pos 399014405 Xid = 629434799

COMMIT/*!*/;

………………………………………………………..省略若干…………………………………………

現(xiàn)在得到確切刪庫的時(shí)間是2018620日上午10:08:44,恢復(fù)時(shí)間就以此為準(zhǔn),稍微往前移一點(diǎn)也是合理的。

這里有一個(gè)小插曲,最開始不加選項(xiàng),簡化執(zhí)行“mysqlbinlog mysql-bin.000864”只有寥寥幾行輸出,輸出結(jié)尾還有一行報(bào)錯(cuò)信息,如下所示:

ERROR: Error in Log_event::read_log_event(): 'Found invalid event in binary log', data_len: 96, event_type: 19

Could not read entry at offset 820:Error in log format or read error

DELIMITER ;

又試著打開其它幾個(gè)二進(jìn)制日志,結(jié)果差不多。加選項(xiàng)執(zhí)行“mysqlbinlog -v --base64-output=DECODE-ROWS mysql-bin.000864|grep -C 10 -i drop”,提示不支持。

mysql刪庫不跑路

這樣看來,恢復(fù)的機(jī)會(huì)不太大了,嚇得趕緊喝泡菜水壓壓驚。用某度搜一下,知道是版本不一致造成的,find 一下,果然有兩個(gè)mysql安裝。這mysql是我?guī)啄昵坝H自部署的,一般都是定制安裝在/usr/local/mysql目錄,數(shù)據(jù)文件分開。但不知道后邊那個(gè)程序員,yum慣了,又給安裝了一個(gè)低版本的。后邊我執(zhí)行帶全路徑,就沒問題,不過我暫時(shí)不想告訴他們,以免大家商和氣。

◆數(shù)據(jù)恢復(fù)

還是使用mysqlbinlog指令,加管道“|”把輸出給mysql,具體的操作如下所示:

[root@db-209 ~]#/usr/local/mysql/bin/mysqlbinlog --database=mobile7_quanzhen --stop-datetime='2018-06-20 10:08:40' mysql-bin.000* |mysql mobile7_quanzhen -p

開始操作的時(shí)候,mysqlbinlog 沒帶選項(xiàng)“--database=mobile7_quanzhen,執(zhí)行后,拋主鍵沖突錯(cuò)誤信息。后在管道右側(cè)mysql這一邊強(qiáng)制強(qiáng)制加選項(xiàng)“-f”,雖然能繼續(xù)往下進(jìn)行,但還是不斷報(bào)主鍵沖突的錯(cuò)誤信息。

mysql刪庫不跑路

后來想,是不是在管道又邊把數(shù)據(jù)庫名字也指定上?反正這樣搞也沒風(fēng)險(xiǎn)。嘿嘿,加上以后,輸入mysql密碼,還真正常導(dǎo)入了。我猜想,不指定數(shù)據(jù)庫選項(xiàng),mysqlbinlog會(huì)嘗試對(duì)所有的庫進(jìn)行恢復(fù),而其它庫卻并沒有丟失數(shù)據(jù),因此造成主鍵沖突。


有一個(gè)有意思的問題,本來在恢復(fù)前導(dǎo)入了舊庫,其所關(guān)聯(lián)的目錄和文件都已經(jīng)生成,但在執(zhí)行mysqlbinlog恢復(fù)時(shí),該庫所對(duì)應(yīng)的目錄里的文件和子目錄會(huì)消失一陣,過一會(huì)又會(huì)自己回來?;謴?fù)繼續(xù)進(jìn)行,可看到數(shù)據(jù)目錄里的文件時(shí)間戳在發(fā)生變化,而不需要恢復(fù)的數(shù)據(jù),其時(shí)間戳是固定的。

mysql刪庫不跑路

恢復(fù)過的數(shù)據(jù),跟最初舊庫導(dǎo)入數(shù)據(jù)的時(shí)間有明顯的差異。恢復(fù)完以后,請(qǐng)程序員幫忙核對(duì)一下,看表的數(shù)量,表的記錄數(shù)是否與刪除前一樣活著差不多。經(jīng)確認(rèn),恢復(fù)成功,大家不用跑路。

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

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

AI