可惡,又是個線上問題

這幾天,在搞 ShardingSphere,這不又來了一個問題嘛,啟動的時候報了一個NPE出來。

好在,這個問題不影響使用,只是啟動會報點錯,接下來,又是辛苦的排查過程。

直接定位到報錯的地方,發現是ShardingSphere在啟動時候去載入表一些元數據資訊報錯,看到這個地方就很明顯的猜測是 map 去 get 的時候報錯了。

一通往上翻源碼,發現這裡定義的是 TreeMap,那應該沒毛病了,就是上面 dataType 是個 null,所以報錯了,可是我還是年輕了。

問題原因

上面我們已經定位到問題出現的地方,接下來就分析下為什麼會出現這個問題呢?

從源碼看到,主要是在這個地方去載入資料庫表的列的元數據資訊。

在這個類里發現了拼接的 SQL 查詢語句,主要是去查 information_schema 下面的 columns 表。

這時候我想看下這個到底是為啥,於是打開本地 debug 看了一下沒有任何問題,然後去測試環境上發現也沒有問題,好像只有生產有這個問題。

這個 dataTypeMap 就是列類型的一個映射,但是本地沒有辦法重現。

本地沒有辦法的話,那就根據上面的 SQL 去生產庫里看了下 COLUMNS 表這個欄位有啥問題,查詢一看,發現了一大堆的 null,還有一些其他的亂七八糟的類型,那看來 NPE 的原因就是因為這些 null 了。

那這些 null 值是怎麼來的呢?根據排查發現都是來自 TIDB 的視圖生成的。本地和測試沒有辦法重現是因為其實用的是 Mysql。

排查

這個環境問題還挺噁心的,因為沒有 TIDB 的環境,只能自己裝一個了去想辦法重現一下了(過程很費時間)。

好在 Mac 裝這些東西還是很方便的,安裝、刷新環境變數、啟動。

1. curl --proto '=https' --tlsv1.2 -sSf //tiup-mirrors.pingcap.com/install.sh | sh
2. source ${your_shell_profile}
3. tiup playground

然後本地按照那個很沙雕的創建視圖的方法創建個視圖出來,再本地 DEBUG 看看。

進來一看,和開始想的不一樣,居然是個 null 字元串,不是我想像中的 null,那這個看起來不應該會報空指針才對啊?!

有點想不通為啥這裡會空,然後打開這個類看了一眼。

嗯???

這尼瑪??

?????

難道是拆箱導致的?

好吧,沒錯。dataTypeMap.get(dataType) 是 null,拆箱調用的啥我不用說了吧,就是這原因。。。

修復

你說咋改?

有同學說了,那還不簡單,你是個沙雕嗎?改成Integer不就完事兒了。

嗯,你說的沒錯,我就這麼改了。

然後,改完之後啟動又是一堆報錯,到處存在調用。

這玩意兒不能動,他彷彿在和我說,你動動試試,果然動動就逝世。

文章寫到這裡,我還沒想好怎麼改,大概有 3 個方案:

  1. 完全去掉 TIDB 還用視圖這離譜的操作,從根源上解決問題
  2. 按照這個方法,改成 Integer,就是不知道要改多少地方
  3. 不去載入視圖的元數據,就可以避免這個問題了,畢竟這年頭誰用視圖啊

給大家個機會,去給他們提個 PR。