溫馨提示×

溫馨提示×

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

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

不使用insert into select的原因有哪些

發(fā)布時間:2021-10-18 17:07:21 來源:億速云 閱讀:134 作者:iii 欄目:編程語言

這篇文章主要介紹“不使用insert into select的原因有哪些”,在日常操作中,相信很多人在不使用insert into select的原因有哪些問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”不使用insert into select的原因有哪些”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

事情的起因

公司的交易量比較大,使用的數(shù)據(jù)庫是mysql,每天的增量差不多在百萬左右,公司并沒有分庫分表,所以想維持這個表的性能只能考慮做數(shù)據(jù)遷移。

同事李某接到了這個任務(wù),于是他想出了這兩個方案

  • 先通過程序查詢出來,然后插入歷史表,再刪除原表

  • 使用insert into select讓數(shù)據(jù)庫IO來完成所有操作

第一個方案使用的時候發(fā)現(xiàn)一次性全部加載,系統(tǒng)直接就OOM了,但是分批次做就過多io和時間長,于是選用了第二種方案,測試的時候沒有任何問題,開開心心上線,然后被開除。

到底發(fā)生了啥,我們復(fù)盤一下

  • 先來看第一個方案,先看偽代碼

// 1、查詢對應(yīng)需要遷移的數(shù)據(jù)
List<Object> list = selectData();

// 2、將數(shù)據(jù)插入歷史表
insertData(list);

// 3、刪除原表數(shù)據(jù)
deleteByIds(ids);

我們可以從這段代碼中看到,OOM的原因很簡單,我們直接將數(shù)據(jù)全部加載內(nèi)存,內(nèi)存不爆才怪。

再來看看第二個方案,到底發(fā)生了啥

為了維持表的性能,同時保留有效數(shù)據(jù),經(jīng)過商量定了一個量,保留10天的數(shù)據(jù),差不多要在表里面保留1kw的數(shù)據(jù)。所以同事就做了一個時間篩選的操作,直接insert into select ... dateTime < (Ten days ago),爽極了,直接就避免了要去分頁查詢數(shù)據(jù),這樣就不存在OOM啦。還簡化了很多的代碼操作,減少了網(wǎng)絡(luò)問題。

為了測試,還特意建了1kw的數(shù)據(jù)來模擬,測試環(huán)境當(dāng)然是沒有問題啦,順利通過??紤]到這個表是一個支付流水表,于是將這個任務(wù)做成定時任務(wù),并且定在晚上8點執(zhí)行。

晚上量也不是很大,自然是沒有什么問題,但是第二天公司財務(wù)上班,開始對賬,發(fā)現(xiàn)資金對不上,很多流水都沒有入庫。最終排查發(fā)現(xiàn)晚上8點之后,陸陸續(xù)續(xù)開始出現(xiàn)支付流水插入失敗的問題,很多數(shù)據(jù)因此丟失。最終定位到了是遷移任務(wù)引起的問題,剛開始還不明所以,白天沒有問題,然后想到晚上出現(xiàn)這樣的情況可能是晚上的任務(wù)出現(xiàn)了影響,最后停掉該任務(wù)的第二次上線,發(fā)現(xiàn)沒有了這樣的情況。

復(fù)盤

  • 問題在哪里?

為什么停掉遷移的任務(wù)之后就好了呢?這個insert into select操作到底做了什么?我們來看看這個語句的explain。 不使用insert into select的原因有哪些 我們不難從圖中看出,這個查詢語句直接走了全表掃描。這個時候,我們不難猜想到一點點問題。如果全表掃描,我們這個表這么大,是不是意味著遷移的時間會很長?假若我們這個遷移時間為一個小時,那是不是意味著就解釋了我們白天沒有出現(xiàn)這樣問題的原因了。但是全表掃描是最根本的原因嗎?

我們不妨試試,一邊遷移,一邊做些的操作,還原現(xiàn)場。最終還是會出現(xiàn)這樣的問題。這個時候,我們可以調(diào)整一下,大膽假設(shè),如果不全表掃描,是不是就不會出現(xiàn)這樣的問題。當(dāng)我們將條件修改之后,果然發(fā)現(xiàn)沒有走了全表掃描了。最終再次還原現(xiàn)場,問題解決了 不使用insert into select的原因有哪些

得出結(jié)論:全表掃描導(dǎo)致了這次事故的發(fā)生。

這樣做就解決了發(fā)生的問題,但是做為陸陸續(xù)續(xù)開始失敗這個就不好解釋了。

  • 原因

在默認的事務(wù)隔離級別下:insert into a select b的操作a表示直接鎖表,b表是逐條加鎖。這也就解釋了為什么出現(xiàn)陸續(xù)的失敗的原因。在逐條加鎖的時候,流水表由于多數(shù)是復(fù)合記錄,所以最終部分在掃描的時候被鎖定,部分拿不到鎖,最終導(dǎo)致超時或者直接失敗,還有一些在這加鎖的過成功成功了。

  • 為什么測試沒有問題?

在測試的時候充分的使用了正式環(huán)境的數(shù)據(jù)來測試,但是別忽視一個問題,那就是測試環(huán)境畢竟是測試環(huán)境,在測試的時候,數(shù)據(jù)量真實并不代表就是真實的業(yè)務(wù)場景。比方說,這個情況里面就少了一個遷移的時候,大量數(shù)據(jù)的插入這樣的情況。最終導(dǎo)致線上bug

解決辦法

既然我們避免全表掃描就可以解決,我們避免它就行了。想要避免全表掃描,對where后面的條件做索引,讓我們的select查詢都走索引即可

insert into還能用嗎?

可以

到此,關(guān)于“不使用insert into select的原因有哪些”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

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

AI