MySQL 的 bug 必须修复吗?
昨晚(1204)邀請在 PingCAP 工作的老弟屈鵬到 dubbogo 社區在線講解 TiDB,其間講到 TiDB 并沒有百分百兼容 MySQL,因為 MySQL 有些 bug,TiDB 將錯就錯照著實現了,而有些 bug 實在無法也去照著兼容實現,線上有社區同學質疑道,MySQL 也有 bug 嗎?
且不論只要是軟件都會有 bug,TiDB 為了兼容 MySQL,其 bug 也要兼容實現,實在令人匪夷所思。其中一些原因是銀行在替換 MySQL 的過程中,對 TiDB 進行評估時,判斷標準是 TiDB 的計算結果與 MySQL 是否一致,TiDB 為了做到結算結果一致,其中一些功能便會依照 MySQL Bug 一并實現。
1 一次思想實驗
這便引申出一個話題,如何在不可靠的軟硬件體系之上構建可靠的計算體系。作為吃瓜群眾一方,我們可以與銀行一方,進行如下思想實驗:
吃瓜群眾:你們銀行方面不知道 MySQL 有 bug 嗎?銀行:我們是知道的。吃瓜群眾:那為何不繞開這個 bug?銀行:含有此 bug 的 MySQL 功能很重要,不能因為這個 bug 便舍棄功能不用。誠如不能因為會拉屎撒尿,便否認熊貓不是可愛的動物。吃瓜群眾:換一個 DB 不行嗎?銀行:bug 分為已知 bug 和 未知 bug,我們使用 MySQL 已久,它的大部分問題我們是清楚的。如果換一個我們不熟悉的 DB,且不說切換后導致的開發運維成本,新 DB 即便保證在這個功能上無 bug,它肯定還有其他潛在的 bug,因為所有的軟件都有 bug。或者說,他們都不會保證他們 100% 不會不出 bug。吃瓜群眾:所有的軟件都必然會有 bug?銀行:是的。就算軟件不會出 bug,底層的硬件體系也不能保證 100% 不出問題。吃瓜群眾:硬件也不可靠嗎?銀行:是的,AWS 就曾出過一次事故,某次陽光紫外線照射到 AWS 的機器內存后,導致一些 bit 位翻轉,而新數據的 checksum 恰好又與老數據的 checksum 一致,這便導致了一次嚴重事故。當然這種事故,大概也只有亞馬遜這種級別的公司有實力和意愿去追究發現,如果資損不嚴重,一般實體是不愿意去深究的。其實我們的整個通信體系也不是 100% 可靠的,譬如 TCP 協議以及其依賴的 IP 層協議包都有一個 checksum 字段,這些都是整個軟硬件體系不可靠的明證。吃瓜群眾:那你們銀行如何保證我們財產的安全性?銀行:針對 MySQL 已有的 bug,如果該功能非主要功能,則事前規避不用。如果該功能很重要,則調查觸發已知 bug 的邊緣條件,然后在上層應用中規避。銀行每天還會進行常規性的對賬,核對資損,通過事后補償的手段保證資金的絕對安全性。2 Go sync.Pool
關于 MySQL bug 的話題,讓我回想起前一陣子 dubbogo 所依賴的網絡庫 getty 遇到的一次問題。今年 9 月 11 日【真是一個好日子】集團相關同學反饋 getty “在一個大量使用短鏈接的場景,XX 發現造成內存大量占用,因為大塊的buffer被收集起來了,沒有被釋放”。
通過定位,發現原因是 sync.Pool 把大量的 bytes.Buffer 對象緩存起來后沒有釋放。集團的同學簡單粗暴地去掉了 sync.Pool 后,問題得以解決。復盤這個問題,其根因是 Go 1.13 對 sync.Pool 進行了優化:在 1.13 之前 pool 中每個對象的生命周期是兩次 gc 之間的時間間隔,每次 gc 后 pool 中的對象會被釋放掉,1.13 之后可以做到 pool 中每個對象在每次 gc 后不會一次將 pool 內對象全部回收。
所以,Go 官方沒有 ”修復“ sync.Pool 的這個 bug ,其上層的 dubbogo 還能穩定運行,當他們 ”修復“ 之后,上層的 dubbogo 運行反而出了問題。
Go 語言 另外一個比較著名的例子便是 godebug=madvdontneed=1。Go 1.12 對其內存分配算法做了改進:Go runtime 在釋放內存時,使用了一個自認為更加高效的 MADV_FREE 而不是之前的 MADV_DONTNEED,其導致的后果是 Go 程序釋放內存后,RSS 不會立刻下降。這影響了很多程序監控指標的準確性,在大家怨聲載道的抱怨后,Go 1.16 又改回了默認的內存分配算法。
3 Gosling 的看法
關于軟件的 bug 是否應該修復這個問題,個人的看法是,對于出現的大部分 bug 我們當然需要修復。但對于一些有著悠久歷史的 bug,需要慎重對待。
今年 11 月,Java之父 James Gosling 在一次名為 ”你需要的軟件可靠性越高,靜態類型語言的幫助就越大“ 的采訪中,有如下論道。
經常讓人感到不適的地方是:如果某個功能存在 bug,人們為這個 bug 采取了變通方法,如果你修復了 bug,你可能會打破這些變通方法。在 Java 世界中,確實有過這樣的例子,我們要么決定不修復 bug,要么引入一種正確的方法,這甚至體現在硬件上。現代的數字世界就是在這套看似 ”不可靠“ 的軟硬件體系之上構建出來的。換言之,我們需要做的是,如何在有 bug 的軟硬件體系上,構建出一個可穩定運轉且最終數據一致的數字世界。即便后退一步,如果做不到數據嚴格一致,如何把資損控制在最小范圍, 控制到我們可接受的范圍內。
總結
以上是生活随笔為你收集整理的MySQL 的 bug 必须修复吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 看透 Go 对象内部细节的神器
- 下一篇: 飞哥:程序员完全没时间提升自己该怎么办?