【踩坑記錄】記一次MySQL主從復(fù)制延遲的坑

最近開發(fā)中遇到的一個MySQL主從延遲的坑,記錄并總結(jié),避免再次犯同樣的錯誤。

情景

一個活動信息需要審批,審批之后才能生效。因為之后活動要編輯,編輯后也可能觸發(fā)審批,審批中展示的是編輯前的活動內(nèi)容,考慮到字段比較多,也要保存審批活動的內(nèi)容,因此設(shè)計采用了一張臨時表,審批中的活動寫進(jìn)審批表(activity_tmp),審批通過之后才把真正的活動內(nèi)容寫進(jìn)活動表(activity)。表的簡要設(shè)計如下,這里將活動內(nèi)容字段合并為content展示:

activity_tmp()
id
status // 審批狀態(tài)    
content //  審批階段提交的活動內(nèi)容

activity
id
content // 審批通過后真正展示的活動內(nèi)容

遇到的問題

當(dāng)時是有編輯觸發(fā)審批的情況,發(fā)現(xiàn)審批通過之后活動內(nèi)容是空的,于是開始追查問題的原因。這里說一句,當(dāng)程序出問題的時候,95%都是代碼的問題,先不要去懷疑環(huán)境出問題。好好的查日志,然后看看你的代碼吧。

追查問題回溯

1、查activity_tmp表,發(fā)現(xiàn)當(dāng)時提交審批的活動內(nèi)容是正常的,而且狀態(tài)也更新為審批通過了,懷疑是寫入activity表失敗
2、查activity表,發(fā)現(xiàn)審批后的內(nèi)容確實沒有寫入,懷疑是代碼問題
3、查看代碼,代碼邏輯沒看出問題,懷疑數(shù)據(jù)庫操作失敗,查看日志
4、日志顯示,有一句insert語句的活動內(nèi)容為空,活動內(nèi)容來自上一個mysql執(zhí)行的是select語句,把該select語句拿出來放到線上的備庫查詢,發(fā)現(xiàn)活動內(nèi)容是存在的。運行時查詢?yōu)榭眨瑘?zhí)行完畢后查詢時內(nèi)容存在,初步懷疑是主從延遲問題。
5、報錯只是部分失敗,確定是主從延遲的問題。

當(dāng)時的問題代碼

$intStatus = $arrInput[‘status’];
$this->objActTmp->updateInfoByAId($intActId, $intStatus);
// 更新后,馬上查
$arrActContent = $this->objActTmp->getActByStatus($intStatus);

這就是主從延遲出現(xiàn)的地方,update后,馬上get,這是主從復(fù)制架構(gòu)上開發(fā)的一個大忌。

解決方案

這類問題的解決方案有兩種:

  • 修改代碼邏輯
  • 修改系統(tǒng)架構(gòu)

對于修改代碼邏輯,鄙人有兩點見解:

  • 如果第二步獲取的數(shù)據(jù)不需要第一步更新的status字段,那就先讀,然后再更新
  • 如果第二步獲取的數(shù)據(jù)需要依賴第一步的status字段,那就在讀出來的時候先判斷是否為空,如果是空的,報錯,下一次重試。

總結(jié)

其實之前也聽到過這樣的例子,但是由于沒有親身經(jīng)歷,所以只保留了一種理論上的記憶,實際上印象不深,經(jīng)歷了這么一次踩坑后,印象特別深刻,現(xiàn)在看到別人寫這樣的代碼也能馬上發(fā)現(xiàn)并指出。還是自己親身去踩坑印象最深。

日志很重要,詳細(xì)的日志更重要。日志要記錄有用的信息,方便追查問題的時候去追溯問題的本質(zhì)原因。我覺得日志就應(yīng)該盡量做成飛機(jī)中的黑匣子,幫助我們保存“事故“發(fā)生時的所有相關(guān)信息。

接下來,會去學(xué)習(xí)主從復(fù)制的原理,敬請期待。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容