歡迎光臨
每天分享高質量文章

MySQL:硬碟在24 * 7工作中罷工了,我該怎麼辦?

來自:碼農翻身(微信號:coderising)
雖然他們不承認, 但我還是這個系統的核心, 因為我儲存著這個系統最最重要的東西:資料。 

 

為了能讓Tomcat他們訪問, 我提供了幾十個資料庫連接——不能提供更多了,因為每個連接都要耗費我不少資源。 

 

這些天Tomcat他們實在不像話,資料庫讀寫的請求像大海的波濤一樣洶涌澎湃,不斷向我襲來。

 

996是別想了, 24*7才是殘酷人生。 

 

我沒辦法, 只好拼命地壓榨硬碟,看著他的磁頭在光滑的盤片上滑來滑去,尋找磁道,定位扇區,讀取資料。這小伙子挺不錯的, 任勞任怨,但是就是太慢,居然比記憶體慢幾千倍。

 

很快,連硬碟也招架不住了,他對我說:“MySQL大哥,再這樣下去我就要壞掉了。”  

 

果然,沒過幾天,硬碟病倒了,系統崩潰了。 

 

讀寫分離

 

第二天我一覺醒來,就發現系統重啟了,但是有點不對勁,這Tomcat發來的SQL怎麼這麼少啊!還都是些Insert, Update, Delete !

 

硬碟對我說:“你還不知道吧,昨天晚上我們的主人張大胖做了個資料庫的讀寫分離!”

 

“讀寫分離?”

 

“是啊, 張大胖統計了一下, 我們讀和寫的比例大概是20:1, 非常適合讀寫分離,簡單來說,就是建立多個資料庫,你是主庫,主要負責寫,還有兩個從庫,主要負責讀。這樣我們就沒有多少壓力了。”

 

 

“我這裡存了這麼多資料, 怎麼複製給另外兩個小弟呢?”   我問道。

 

“這你不用擔心,張大胖昨天已經給你做了一個快照,他把快照已經複製到了那兩個小弟那裡。接下來你只需要把今天早上產生的新的資料發過去就行了。”

 

基於SQL陳述句的複製

 

正在這個時候,那個叫旺財的小弟給我打招呼了: “大哥,你把你那裡的執行過的Insert, Update, Delete這樣的SQL陳述句都記錄下來,然後發給我和小強,我們倆要這些SQL在我們自己的資料庫上’重放’一下!”

 

 

我看了一下自己的配置,果然如此,我只需要把SQL陳述句發過去就OK了。 

 

有了兩個小弟的承接讀操作,我的工作大大減輕,又可以和硬碟喝茶聊天了。 

 

可是沒多久,Tomcat氣衝衝地來質問我:“你們怎麼搞的,資料出現不一致了,Order表, rand_num那一列!”

 

這是怎麼回事?  我可是把所有的SQL陳述句都發給旺財和小強執行了啊,怎麼會不一致?

 

我們三個不敢怠慢, 趕緊翻看最近執行的SQL, 尤其是更新Order表, rand_num列相關的。 

 

終於發現了罪魁禍首,就是這個函式: RAND() , 它會傳回一個隨機數, 經過處理後,更新到rand_num這一列。

 

在不同的資料庫執行,這個函式傳回的值也就不同,這就會導致我們的資料不一致了。

 

我感到非常羞愧,因為資料的一致性是我們資料庫家族最引以為豪的特性。 在單機的時候,我們自己就可以通過事務來保證了。 但是一旦有多個資料庫,形成了分佈式的環境,想讓大家都保持一致,怎麼會這麼麻煩?

 

我們只好請張大胖手工把資料改成一致的, 然後再想新的辦法。

 

基於行的複製

 

小強說道:“大哥,我提議一個新方法,以後你別記錄SQL了,你只記錄SQL的所影響的行和相關的值,然後把這些日誌發給我們,例如:

 

對於Insert, 記錄下所有列的新值

對於Delete記錄下到底是哪一行被刪除(用主鍵來標識)

對於Update記錄下哪一行被更新(用主鍵來標識),以及被更新的列和新值

 

有了這些日誌,我們就可以清楚地知道你那邊到底發生了什麼變化,我們把這些日誌應用到我們的資料庫上就可以了!”

 

鑒於上一次的教訓,這次我們仔細分析各種例外情況,確保沒有問題才正式採用。

 

我,旺財和小強通力合作,新的複製方式工作得很好。直到有一天我們遇到了一個Update陳述句:

 

update xxx set flag = 0;

 

這個陳述句一下子更新了幾十萬條資料。 在之前使用基於SQL的複製時,記錄下這一條陳述句就行了。 用現在的方式,得記錄幾十萬條資料,這太要命了!

 

怎麼辦? 退回到原來的“基於SQL的複製”,肯定不行! 

 

要不預設用SQL複製? 如果SQL執行結果“不確定”,例如有RAND()函式呼叫,那我們就使用陳述句複製。 

 

這是一種混合的樣式,雖然麻煩,但也只能如此了。

 

資料延遲

 

深更半夜Tomcat又來找我:“有個用戶在咱們發了一個帖子,我在你這裡做了Insert 操作,然後用戶掃清頁面的時候,我從旺財那裡讀取資料,卻讀不到! 現在人家來投訴我們了!”

 

 

我心想,這家伙也太快了吧, 居然比我複製資料的速度還快。

 

我又檢查了一下我和旺財之間的複製通道,由於網絡原因,確實是有點延遲。

 

我對Tomcat說:“這是小事情,複製很快完成,他多掃清幾次肯定就可以了。”

 

Tomcat怒道:“這是嚴重的用戶體驗問題,怎麼是小事?”

 

“資料複製延遲多正常啊,反正我們三個能保證最終的一致性!”

 

Tomcat說:“最終一致性? 在我這裡可不行! 我給你們出個主意,我在insert資料的時候,你還沒有複製完成,怎麼就給我說已經insert成功了? 你必需得等到資料複製完成才能說insert成功!! 你的正確次序應該是這樣的。”

 

 

旺財一看到這個圖,大驚失色:“萬萬不可, 這樣一來就是同步複製了,如果網絡比較慢, 第2.1和第2.2步遲遲不能完成, 那我們大哥就沒法告訴你插入資料成功, 用戶連帖子都發表不了!”

 

“是啊,這種用戶體驗會更差!” 小強幫腔。 

 

Tomcat說:“我不管,反正是你們的問題!你們資料庫得想辦法解決!”

 

我說:“這個問題啊,本質上是資料延遲導致的,但是在分佈式環境下這是不可避免的,我們在資料庫層面是解決不了的, 你們在應用層面多想想辦法吧。”

 

“能有什麼辦法?”

 

我說: “比如,對於不能容忍延遲的操作,都在我這裡(主庫)來讀寫,或者用個什麼方法判斷主庫和從庫是不是已經一致了。”

 

“也可以用個取巧的辦法, 讓用戶發表完帖子後等個幾秒鐘再來掃清……”  旺財補充。

 

Tomcat嘆了一口氣:“唉,你們這些家伙啊, 只會推卸責任! 這我可管不了, 我們看看張大胖主人會怎麼辦吧!”

 

對於這種資料複製延遲的問題, 你會怎麼辦呢? 歡迎留言討論!  

 

作者簡介:

劉欣,前IBM架構師,近20年從業經驗,”碼農翻身”公眾號作者,暢銷書《碼農翻身》作者,用故事講解技術是拿手好戲。 撥開技術迷霧,輕鬆瞭解技術本質,從”碼農翻身”開始。

赞(0)

分享創造快樂