亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:52000
  • 待審:37
  • 小程序:12
  • 文章:1037587
  • 會(huì)員:756

想必大家都聽說過刪庫跑路吧,我之前一直把它當(dāng)一個(gè)段子來看。

可萬萬沒想到,就在昨天,我們公司的某位員工,竟然寫了一個(gè)比刪庫更可怕的 Bug!

給大家分享一下(不是公開處刑),希望朋友們引以為戒。

一、Bug 起因

事情是這樣的,昨天中午 11 點(diǎn)左右,突然用戶群里的小伙伴反饋:自己直接成為了 魚聰明 AI 網(wǎng)站 的管理員!

接下來,陸續(xù)有更多同學(xué)反饋:大家都成管理員了!

看到這里,我立刻就去查了下數(shù)據(jù)庫,結(jié)果看到的是:

好家伙,早起腦供血不足的我立刻高血壓上來了,怎么所有的用戶都變成管理員了?!

我趕緊問下我所有的員工,這特么是誰干的!!!

然后員工小 A 大叫:“我 X,是我今天執(zhí)行單元測(cè)試更新數(shù)據(jù)的時(shí)候,少加了個(gè) where 條件!”

本來的預(yù)期:update user set userRole = 'admin' where id = 1

實(shí)際上執(zhí)行:update user set userRole = 'admin'

于是導(dǎo)致整個(gè)庫里的所有用戶都變成了管理員,大家可以愉快地薅魚毛了。

二、緊急處理

后來據(jù)這位寫 Bug 的同學(xué)的回憶,由于她之前沒有遇到過類似的情況,第一時(shí)間腦袋是一片空白、頭嗡嗡的,完全不知道接下來要怎么做。

不過我是很冷靜的,因?yàn)橹霸诠咎幚磉^類似的情況,畢竟曾經(jīng)凌晨 4 - 5 點(diǎn)的時(shí)候都被叫起來過。。。

所以立刻就給他發(fā)了一段處理方式:

解釋一下,就跟我們?cè)诼飞峡吹揭黄鸾煌ㄊ鹿室粯樱谝粫r(shí)間要么是保護(hù)現(xiàn)場(chǎng),放一個(gè)小牌牌不讓大家進(jìn)到事故發(fā)生地;要么就是防止擴(kuò)大影響,人工疏導(dǎo)不讓更多人圍觀、阻塞交通。

一般這兩件事情是同時(shí)執(zhí)行的,由于我知道怎么能夠判定哪些用戶本來是 VIP(比如通過 VIP 信息)、而且程序又有詳細(xì)的日志,所以第一時(shí)間是讓員工先把 user 表的所有角色設(shè)置為普通用戶權(quán)限,防止有人繼續(xù)利用管理員權(quán)限去做一些不好的事情。

接下來就是立刻停止了線上的前后端服務(wù),一方面是為了后面好恢復(fù)數(shù)據(jù),另外也是防止一些同學(xué)發(fā)現(xiàn)自己突然從會(huì)員變成了普通用戶,增加大量的人工咨詢成本。

所以當(dāng)時(shí)很多同學(xué)訪問魚聰明時(shí),看到了這樣的截圖:

穩(wěn)定現(xiàn)場(chǎng)后,接下來就是想辦法恢復(fù)數(shù)據(jù)到正常的狀態(tài),好在我給數(shù)據(jù)庫設(shè)置了分鐘級(jí)別的備份,可以直接把數(shù)據(jù)恢復(fù)到事故發(fā)生前的最近正常的時(shí)間點(diǎn)。

有了備份后的老數(shù)據(jù),還要考慮恢復(fù)這個(gè)時(shí)間點(diǎn)后新增的用戶數(shù)據(jù)。

有很多種恢復(fù)策略,我優(yōu)先選擇了邏輯最簡(jiǎn)單的策略:直接更新用戶 updateTime > '2023-07-20 10:00:00' 的數(shù)據(jù),根據(jù) id 點(diǎn)對(duì)點(diǎn)覆蓋除了 userRole 之外的數(shù)據(jù)列;如果沒有對(duì)應(yīng)的 id,新增一條數(shù)據(jù)。也就是使用類似 saveOrUpdate 的方法。

理想很豐滿,現(xiàn)實(shí)很殘酷。萬萬沒想到,由于 updateTime 是一個(gè)發(fā)生數(shù)據(jù)修改時(shí)自動(dòng)更新的字段,導(dǎo)致所有的數(shù)據(jù) updateTime 全是最新的,相當(dāng)于要把數(shù)據(jù)庫全量的數(shù)據(jù)都去比較一遍。

于是我的員工呢,寫了類似下面這樣的程序:

然后就開始執(zhí)行了,結(jié)果執(zhí)行了很久很久,數(shù)據(jù)都沒更新完。

看來單線程還是太慢了,于是我用并發(fā)編程的方式改進(jìn)了同步的過程。先把所有用戶分組,然后多線程同時(shí)執(zhí)行 saveOrUpdateBatch 方法。

示例代碼如下:

void restoreUserTable() {

List<User> userList = userService.list();

List<UserBak> userBakList = userList.stream().map(user -> {

user.setUserRole(null);

UserBak userBak = new UserBak();

BeanUtils.copyProperties(user, userBak);

return userBak;

}).collect(Collectors.toList());

int batchSize = 1000;

// 使用 lambda 表達(dá)式將 userList 每1000個(gè)元素分為一組

List<List<UserBak>> groupedBakUsers = IntStream.range(0, userList.size())

.boxed()

.collect(Collectors.groupingBy(index -> index / batchSize)) // 將索引按組分組

.values()

.stream()

.map(indices -> indices.stream()

.map(userBakList::get) // 根據(jù)索引獲取 User 對(duì)象

.collect(Collectors.toList())) // 每組1000個(gè)元素的列表

.collect(Collectors.toList()); // 所有分組的列表

List<CompletableFuture<Void>> completableFutureList = new ArrayList<>();

int i = 1;

for (List<UserBak> groupedBakUser : groupedBakUsers) {

int finalI = i;

CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {

boolean b = userBakService.saveOrUpdateBatch(groupedBakUser, batchSize);

});

i++;

completableFutureList.add(completableFuture);

}

CompletableFuture.allOf(completableFutureList.toArray(new CompletableFuture[]{})).join();

}

使用這種方式,很快數(shù)據(jù)就恢復(fù)完成了。

當(dāng)然,還有更簡(jiǎn)單的方式,比如聯(lián)表查詢、對(duì)比哪些數(shù)據(jù)行發(fā)生了變動(dòng),再去做修改。只不過當(dāng)時(shí)情況緊急、再加上數(shù)據(jù)庫量級(jí)可控,我們選擇了相對(duì)理解成本最低的方式。

之后,我這邊又手動(dòng)做了一次全量備份,并且思考了一下還有沒有遺漏的問題,才恢復(fù)上線。

三、事后復(fù)盤

整個(gè)事故時(shí)長(zhǎng)接近 2 個(gè)小時(shí),大致分為:

  • 人工發(fā)現(xiàn)事故(30 分鐘后通過用戶反饋才得知)
  • 定位問題(5 - 10 分鐘)
  • 策略制定和同步(5 - 10 分鐘)
  • 數(shù)據(jù)備份恢復(fù)(15 分鐘)
  • 增量數(shù)據(jù)同步(40 分鐘)
  • 上線前備份(10 分鐘),同時(shí)進(jìn)行其他考慮

從某種意義上來說,這次的事故比直接刪庫更嚴(yán)重!因?yàn)閯h庫了趕緊恢復(fù)就好,但這次不僅出現(xiàn)了 “數(shù)據(jù)污染”,還出現(xiàn)了 “越權(quán)” 的問題,我們網(wǎng)站內(nèi)僅管理員可見的敏感信息會(huì)存在泄露風(fēng)險(xiǎn)。好在我們也沒什么敏感信息哈哈。

還有就是用戶可能會(huì)利用漏洞來薅魚毛(管理員可以大量獲取),但經(jīng)過我們的統(tǒng)計(jì),這段時(shí)間利用漏洞薅魚毛的人數(shù)寥寥無幾,大家都是非常善良的,這才放下心來。

雖然這次的事故帶來的損失不是特別大,但也發(fā)現(xiàn)了我們系統(tǒng)存在的問題。

我也跟這位員工說:出了事情不可怕,可怕的是不知道改正,出現(xiàn)同樣的事情。

那么應(yīng)該如何防止出現(xiàn)類似的事故呢?

1、控制操作權(quán)限

為了防止用戶執(zhí)行 update、delete 操作時(shí)不小心漏掉了 where 條件、直接更新全量數(shù)據(jù),企業(yè)中一般是會(huì)禁止不帶 where 條件的修改操作的。

出現(xiàn)這次的事故后,我也立刻給 MySQL 開啟了 sql_safe_updates 配置:

缺少 where 條件的更新會(huì)直接觸發(fā)下列報(bào)錯(cuò):

之前為什么沒加?主要是因?yàn)橐郧岸际亲约阂粋€(gè)人開發(fā)系統(tǒng),而且會(huì)有需要全量更新的場(chǎng)景,圖省事兒。

2、生產(chǎn)環(huán)境隔離

正常情況下,不應(yīng)該允許直接在本地連接和操作線上數(shù)據(jù)庫的數(shù)據(jù)。而是需要先編寫代碼、提交代碼審核、發(fā)布上線后,再執(zhí)行修改操作。

像這次的事故,如果員工不是本地直接更新數(shù)據(jù)庫,而是提交代碼給我看一下,我大概率就會(huì)發(fā)現(xiàn)他少寫了更新條件,就能防止了。

其實(shí)之前在騰訊的時(shí)候,我都會(huì)嚴(yán)格注意這些事項(xiàng)的。但之所以現(xiàn)在自己公司的項(xiàng)目是允許員工在本地連接線上的,想必大家也能猜到原因 —— 業(yè)務(wù)規(guī)模小、人數(shù)少,直接在同一個(gè)庫開發(fā)會(huì)方便一些。

但如果項(xiàng)目的規(guī)模上來了,一定要做好多套環(huán)境的隔離,本地環(huán)境、測(cè)試環(huán)境、預(yù)發(fā)布環(huán)境、線上環(huán)境都要嚴(yán)格區(qū)分了。

3、SQL 審批

之前在騰訊的時(shí)候,想要修改關(guān)鍵庫的數(shù)據(jù),不能直接執(zhí)行 SQL 語句,而是要先把 SQL 語句提交到審核平臺(tái),等你的領(lǐng)導(dǎo)和數(shù)據(jù)庫運(yùn)維確認(rèn)沒問題后,才能執(zhí)行。這樣每條 SQL 都是至少有 2 個(gè)人看過的,能夠大大增加安全性。

曾經(jīng)我覺得這種機(jī)制很麻煩,但經(jīng)歷過一些血淚教訓(xùn)后,才意識(shí)到這個(gè)環(huán)節(jié)真的是泰褲辣!

4、數(shù)據(jù)庫審計(jì)

數(shù)據(jù)庫審計(jì)是指記錄和監(jiān)控?cái)?shù)據(jù)庫的訪問及 SQL 語句執(zhí)行情況,從而精細(xì)化風(fēng)險(xiǎn)控制,提高數(shù)據(jù)安全性。

可以自己在數(shù)據(jù)庫配置(比如開啟日志、使用審計(jì)插件等),也可以使用第三方云服務(wù)自帶的審計(jì)規(guī)則配置。

5、提升風(fēng)險(xiǎn)意識(shí)

最不需要技術(shù),卻也是最重要的一點(diǎn),那就是要讓團(tuán)隊(duì)的所有同學(xué)意識(shí)到這件事情帶來的風(fēng)險(xiǎn)、問題的嚴(yán)重性。

因?yàn)槟阌肋h(yuǎn)叫不醒一個(gè)裝睡的人,同理,再多的防護(hù)也限制不了本身就想搞事的人。

所以這件事情是我和這位員工共同的責(zé)任,作為懲罰,我們決定請(qǐng)其他同事喝奶茶。就這么愉快地決定了~

不過也有做的好的地方,比如做了完整又靈活的數(shù)據(jù)備份,這是線上項(xiàng)目必備的操作。

以上就是本期分享,希望大家不僅是看個(gè)樂,也能有一些收獲和啟發(fā),不過希望大家都不要遇到這類鬧心的事情。

作者丨程序員魚皮

來源丨公眾號(hào):程序員魚皮(ID:coder_yupi)

分享到:
標(biāo)簽:Bug
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 52000

    網(wǎng)站

  • 12

    小程序

  • 1037587

    文章

  • 756

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定