您好,登錄后才能下訂單哦!
上周夜里,一個(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è)2018年6月9日的備份存在。本來一直都在自動(dòng)備份的,后來由于要遷移,而且據(jù)說近期夜間備份時(shí),非常占用資源,負(fù)載老高,到上午上班時(shí),備份壓縮那一步還沒有結(jié)束,就把備份給停了。
這是遷移部分?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í)間戳是6月17號(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操作?回答說是6月20號(hào)上午10點(diǎn)過幾分。有了這個(gè)參照點(diǎn),再查看二進(jìn)制日志文件的時(shí)間戳,就可定位到文件“mysql-bin.000864”,確定這個(gè)文件的原因是文件“mysql-bin.000863”的最后寫入時(shí)間是“6月20日4: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í)間是2018年6月20日上午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”,提示不支持。
這樣看來,恢復(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ò)誤信息。
后來想,是不是在管道又邊把數(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í)間戳是固定的。
恢復(fù)過的數(shù)據(jù),跟最初舊庫導(dǎo)入數(shù)據(jù)的時(shí)間有明顯的差異。恢復(fù)完以后,請(qǐng)程序員幫忙核對(duì)一下,看表的數(shù)量,表的記錄數(shù)是否與刪除前一樣活著差不多。經(jīng)確認(rèn),恢復(fù)成功,大家不用跑路。
免責(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)容。